package com.twetec.cms.adapter.pc.backend.controller.website;

import cn.hutool.core.io.FileUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.twetec.cms.adapter.pc.backend.annotion.SitePermission;
import com.twetec.cms.adapter.pc.backend.response.R;
import com.twetec.cms.adapter.pc.backend.response.ResultCodeMsgEnum;
import com.twetec.cms.adapter.pc.backend.util.beetl.html.BeetlStaticHtml;
import com.twetec.cms.common.constant.ArticleEnum;
import com.twetec.cms.common.constant.FileConst;
import com.twetec.cms.common.constant.StaticHtmlStatusEnum;
import com.twetec.cms.common.constant.StaticHtmlTypeEnum;
import com.twetec.cms.common.util.validate.ValidateUtil;
import com.twetec.cms.model.po.search.SearchArticlePO;
import com.twetec.cms.model.po.system.StaticLogPO;
import com.twetec.cms.model.po.user.UserPO;
import com.twetec.cms.model.po.website.*;
import com.twetec.cms.model.vo.website.*;
import com.twetec.cms.service.file.FastdfsFileService;
import com.twetec.cms.service.search.SearchArticleService;
import com.twetec.cms.service.system.StaticLogService;
import com.twetec.cms.service.ucenter.UserService;
import com.twetec.cms.service.website.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;


@Api(tags = "文章模块")
@RestController
@RequestMapping("/website/article")
public class ArticleController {

    @Value("${twetec.resource.storage-root-path}")
    private String rootPath;

    @Value("${twetec.resource.preview-root-url}")
    private String previewUrl;

    @Autowired
    private SearchArticleService searchArticleService;

    @Autowired
    private ArticleService articleService;

    @Autowired
    private FastdfsFileService fastdfsFileService;

    @Autowired
    private ColumnArticleModelService columnArticleModelService;

    @Autowired
    private ArticleModelService articleModelService;

    @Autowired
    private ArticleExtendService articleExtendService;

    @Autowired
    private ArticleAttachmentService articleAttachmentService;

    @Autowired
    private ArticleRelevantService articleRelevantService;

    @Autowired
    private UserService userService;

    @Autowired
    private ColumnService columnService;

    @Autowired
    private SiteColumnService siteColumnService;

    @Autowired
    private SiteService siteService;

    @Autowired
    private BeetlStaticHtml beetlStaticHtml;

    @Autowired
    private WebsiteTemplateService websiteTemplateService;

    @Autowired
    private ColumnReferenceArticleService columnReferenceArticleService;

    @Autowired
    private ColumnReferenceRelationshipService columnReferenceRelationshipService;
    private StaticHtmlController staticHtmlController;

    @Autowired
    private StaticLogService staticLogService;

    @Value("${twetec.resource.preview-root-path}")
    private String previewPath;

    private static final String CREATE = "article:create";
    private static final String ARTICLE_PAGE = "article:page-search-list";
    private static final String GET_ARTICLE_STATUS_COUNT = "article:get-article-status-count";
    private static final String UPDATE_BY_ID = "article:update-by-id";
    private static final String RELEASE_BY_ID = "article:release-by-id";
    private static final String RELEASE_BY_IDS = "article:release-by-ids";
    private static final String ARTICLE_COPY_BY_ID = "article:article-copy-by-id";
    private static final String ARTICLE_COPY_BY_IDS = "article:article-copy-by-ids";
    private static final String MOVE_BY_ID = "article:move-by-id";
    private static final String MOVE_BY_IDS = "article:move-by-ids";
    private static final String GET_PC_TEMPLATE_RENDER_CONTENT = "article:get-pc-template-render-content";
    private static final String GET_H5_TEMPLATE_RENDER_CONTENT = "article:get-h5-template-render-content";
    private static final String REMOVE_BY_ID = "article:remove-by-id";
    private static final String REMOVE_BY_IDS = "article:remove-by-ids";
    private static final String VERIFY_BY_ID = "article:verify-by-id";
    private static final String VERIFY_BY_IDS = "article:verify-by-ids";
    private static final String GET_VERIFY_REASON_BY_ID = "article:get-verify-reason-by-id";
    private static final String ARTICLE_DETAIL = "article:get-by-id";
    private static final String OFF_SHELF_BY_ID = "article:off-shelf-by-id";
    private static final String OFF_SHELF_BY_IDS = "article:off-shelf-by-ids";
    private static final String RECOVERY_BY_ID = "article:recovery-by-id";
    private static final String RECOVERY_BY_IDS = "article:recovery-by-ids";


    @ApiOperation(value = "上传封面", notes = "上传封面")
    @PostMapping("/upload-cover")
    public R<ImageFileNameVO> uploadCover(@ApiParam(value = "file", required = true, example = "1.html") @RequestParam(required = false) MultipartFile file) {

        // 校验上传文件是否为空
        if (null == file) return R.failureRequestParam().msg("上传文件参数为空");
        // file.getOriginalFilename()得到上传时的文件名(仅返回文件名,并不会包含路径) 并校验是否是图片
        if (!ValidateUtil.isPicture(file.getOriginalFilename())) return R.failureRequestParam().msg("该文件不是图片");

        // file.getSize()以字节为单位返回指定文件的大小   <2M
        if (file.getSize() > FileConst.UPLOAD_LOGO_PICTURE_SIZE)
            return R.failureRequestParam().msg("图片大小不能超过" + FileConst.UPLOAD_LOGO_PICTURE_SIZE + "M");

        String fileUrl = fastdfsFileService.uploadSiteLogo(file);

        // 上传失败
        if (null == fileUrl) return R.failure();

        // 返回文件路径
        ImageFileNameVO imageFileNameVO = new ImageFileNameVO();
        imageFileNameVO.setFileUrl(fileUrl);
        return R.success().data(imageFileNameVO);
    }

    @ApiOperation(value = "上传附件", notes = "上传附件")
    @PostMapping("/upload-attachment")
    public R<ImageFileNameVO> uploadAttachment(@ApiParam(value = "file", required = true, example = "1.html") @RequestParam(required = false) MultipartFile file) {

        // 校验上传文件是否为空
        if (null == file) return R.failureRequestParam().msg("上传的附件参数为空");

        // file.getSize()以字节为单位返回指定文件的大小   <100M
        if (file.getSize() > FileConst.UPLOAD_FILE_MAX_SIZE)
            return R.failureRequestParam().msg("上传的附件大小不能超过" + FileConst.UPLOAD_FILE_MAX_SIZE + "M");

        String fileUrl = fastdfsFileService.uploadAttachment(file);
        // 失败
        if (null == fileUrl) return R.failure();

        // 文件名
        String originalFilename = file.getOriginalFilename();

        // 返回文件路径
        ImageFileNameVO imageFileNameVO = new ImageFileNameVO();
        imageFileNameVO.setFileUrl(fileUrl);
        imageFileNameVO.setFileName(originalFilename);
        return R.success().data(imageFileNameVO);
    }

    @ApiOperation(value = "根据栏目id获取文章扩展信息", notes = "根据栏目id获取文章扩展信息")
    @GetMapping("/get-extend-field-list-by-column-id")
    public R<ExtendFieldListVO> getExtendFieldListByColumnId(@ApiParam(value = "columnId", required = true, example = "12312313123") @RequestParam(required = false) Long columnId) {

        // 校验columnId
        if (columnId == null || !ValidateUtil.Number(columnId)) return R.failureRequestParam().msg("栏目id输入有误");

        // 返回的VO
        ExtendFieldListVO extendFieldListVO = new ExtendFieldListVO();
        extendFieldListVO.setExtendFieldList("");

        // 现根据栏目id查询对应的文章模型id
        QueryWrapper<ColumnArticleModelPO> columnArticleModelPOQueryWrapper = new QueryWrapper<>();
        columnArticleModelPOQueryWrapper.eq("COLUMN_ID", columnId);
        columnArticleModelPOQueryWrapper.last(" AND ROWNUM = 1");
        ColumnArticleModelPO columnArticleModelPO = columnArticleModelService.getOne(columnArticleModelPOQueryWrapper);

        // 如果栏目id没有查到文章模型
        if (columnArticleModelPO == null) return R.success().data(extendFieldListVO);
        // 根据文章模型id获取到文章模型信息
        ArticleModelPO articleModelPO = articleModelService.getById(columnArticleModelPO.getArticleModelId());
        // 如果文章模型id没有查到
        if (articleModelPO == null) return R.success().data(extendFieldListVO);

        extendFieldListVO.setExtendFieldList(articleModelPO.getExtendFieldList());

        return R.success().data(extendFieldListVO);

    }

    @SitePermission({CREATE})
    @ApiOperation(value = "新增文章", notes = "新增文章")
    @Transactional
    @PostMapping("/create")
    public R<ArticleCreateVO> create(@ApiParam(value = "站点id", required = true, example = "123456789") @RequestParam(required = false) Long siteId,
                                     @ApiParam(value = "所属栏目", required = true, example = "12312313123") @RequestParam(required = false) Long columnId,
                                     @ApiParam(value = "文章标题", required = true, example = "文章标题xxx") @RequestParam(required = false) String title,
                                     @ApiParam(value = "文章属性(文字WEN_ZI,图片TU_PIAN,视频SHI_PIN)", required = true, example = "WEN_ZI") @RequestParam(required = false) String attribute,
                                     @ApiParam(value = "文章类型(图文资讯TU_WEN_ZI_XUN,下载文件XIA_ZAI_WEN_JIAN,跳转链接TIAO_ZHUAN_LIAN_JIE,公告资讯GONG_GAO_ZI_XUN)", required = true, example = "TU_WEN_ZI_XUN") @RequestParam(required = false) String type,
                                     @ApiParam(value = "发布渠道(PC,H5,API),用英文逗号隔开", required = true, example = "PC") @RequestParam(required = false) String releaseChannel,
                                     @ApiParam(value = "内容", required = false, example = "文章内容") @RequestParam(required = false) String content,
                                     @ApiParam(value = "来源", required = true, example = "新浪微博") @RequestParam(required = false) String origin,
                                     @ApiParam(value = "作者", required = true, example = "一个作家") @RequestParam(required = false) String author,
                                     @ApiParam(value = "发布时间(10位时间戳)", required = true, example = "1234567891") @RequestParam(required = false) Date releaseTime,
                                     @ApiParam(value = "公告开始时间(10位时间戳)", required = false, example = "1234567891") @RequestParam(required = false) Date gmtAnnouncementStart,
                                     @ApiParam(value = "公告结束时间(10位时间戳)", required = false, example = "201234567891") @RequestParam(required = false) Date gmtAnnouncementEnd,
                                     @ApiParam(value = "封面图(多张使用json形式存储)", required = false, example = "[{\"fileName\":\"icon_ghhy.png\",\"fileUrl\":\"http://10.23.222.147:8888/group1/M00/00/E6/Chfek2FkZB2EC0HqAAAAAHqO59E396.png\"}]") @RequestParam(required = false) String coverListJson,
                                     @ApiParam(value = "封面图类型(单图DAN_TU,多图DUO_TU,横图HENG_TU)", required = true, example = "DAN_TU") @RequestParam(required = false) String coverType,
                                     @ApiParam(value = "文章摘要", required = false, example = "文章摘要xxx") @RequestParam(required = false) String summary,
                                     @ApiParam(value = "排序的文章id排序的文章id(如果是自定义类型的，此文章要插入到一篇文章后面，传该文章id)", required = false, example = "5643216552156") @RequestParam(required = false) Long sortArticleId,
                                     @ApiParam(value = "排序类型(置顶ZHI_DING,发布时间FA_BU_SHI_JIAN,自定义ZI_DING_YI)", required = false, example = "ZHI_DING") @RequestParam(required = false) String sortType,
                                     @ApiParam(value = "seo标题", required = false, example = "新闻") @RequestParam(required = false) String seoTitle,
                                     @ApiParam(value = "seo关键字(字符串类型用英文逗号隔开)", required = false, example = "大新闻,社会新闻") @RequestParam(required = false) String seoKeywords,
                                     @ApiParam(value = "seo描述", required = false, example = "大新闻,社会新闻") @RequestParam(required = false) String seoDesc,
                                     @ApiParam(value = "扩展信息", required = false, example = "[{\"fieldCode\":\"test_1\",\"fieldAliase\":\"test_122\",\"inputType\":\"text\",\"fieldName\":\"test_122\",\"isRequired\":false,\"isSearch\":false,\"defaultValue\":\"test_122\",\"maxlength\":\"255\",\"description\":\"test_122\",\"check\":true,\"isExtend\":true,\"id\":1632289118936,\"sort\":0}]") @RequestParam(required = false) String extendFieldListJason,
                                     @ApiParam(value = "相关文章(Json字符串)", required = false, example = "[{\"relevantArticleId\":\"156456412\",\"relevantArticleId\":\"798564156456\"}]") @RequestParam(required = false) String articleRelevantListJson,
                                     @ApiParam(value = "附件列表(Json字符串)", required = false, example = "[{\"attachmentUrl\":\"http://xxxxx.com/xxx.zip\",\"attachmentName\":\"name1\"},{\"attachmentUrl\":\"http://xxxxx.com/xxx.txt\",\"attachmentName\":\"name2\"}]") @RequestParam(required = false) String attachmentListJson,
                                     @RequestAttribute("userId") Long userId) {

        if (siteId == null || !ValidateUtil.Number(siteId) || siteId <= 0)
            return R.failureRequestParam().msg("站点id不能为空");
        // 校验columnId
        if (columnId == null || !ValidateUtil.Number(columnId)) return R.failureRequestParam().msg("栏目id输入有误");
        if (StringUtils.isEmpty(title)) return R.failureRequestParam().msg("文章标题不能为空");
        if (StringUtils.isEmpty(attribute)) return R.failureRequestParam().msg("文章属性不能为空");
        if (StringUtils.isEmpty(type)) return R.failureRequestParam().msg("文章类型不能为空");
        if (StringUtils.isEmpty(releaseChannel)) return R.failureRequestParam().msg("发布渠道不能为空");
        if (StringUtils.isEmpty(origin)) return R.failureRequestParam().msg("来源不能为空");
        if (StringUtils.isEmpty(author)) return R.failureRequestParam().msg("作者不能为空");
        if (null == releaseTime) return R.failureRequestParam().msg("发布时间不能为空");
        if (StringUtils.isEmpty(coverType)) return R.failureRequestParam().msg("封面图类型不能为空");
        if (StringUtils.isNotEmpty(type) && type.equals(ArticleEnum.TYPE_GONG_GAO_ZI_XUN.getValue()) && (gmtAnnouncementStart == null || gmtAnnouncementEnd == null)) {
            return R.failureRequestParam().msg("当文章类型为公告资讯时，文章的公告开始时间和公告结束时间不能为空！");
        }


        // 新增文章基本信息，返回文章id
        ArticlePO article = articleService.saveArticle(siteId, columnId, title, attribute, type, releaseChannel, origin, author, releaseTime, gmtAnnouncementStart, gmtAnnouncementEnd, coverListJson, coverType, summary, sortArticleId, sortType, userId);
        if (article.getId() == null) return R.failure().msg("添加失败");
        // 保存或更新扩展信息
        articleExtendService.saveOrUpdateArticleExtend(article.getId(), content, seoTitle, seoKeywords, seoDesc, extendFieldListJason, userId);
        // 保存或更新附件信息
        articleAttachmentService.saveOrUpdateAttachment(article.getId(), attachmentListJson, userId);
        // 保存或更新相关文章信息
        articleRelevantService.saveOrUpdateRelevent(article.getId(), articleRelevantListJson, userId);

        ColumnPO columnPO = columnService.getById(columnId);
        if (null != columnPO) {
            article.setColumnName(columnPO.getName());
            article.setColumnXpath(columnPO.getXpath());
        }
        // 添加文章到全文检索
        SearchArticlePO searchArticlePO = p_copyArticleToSearchArticle(article, content, seoKeywords);
        try {
            searchArticleService.addDoc(searchArticlePO);
        } catch (Exception e) {
            e.printStackTrace();
            R.failure().msg("操作失败");
        }

        // 根据当前文章的所属栏目，去关系表中查当前栏目有没有被其他栏目引用
        QueryWrapper<ColumnReferenceRelationshipPO> columnReferenceRelationshipPOQueryWrapper = new QueryWrapper<>();
        columnReferenceRelationshipPOQueryWrapper.eq("REFERENCE_COLUMN_ID", columnId);
        List<ColumnReferenceRelationshipPO> relationshipPOList = columnReferenceRelationshipService.list(columnReferenceRelationshipPOQueryWrapper);
        if (null != relationshipPOList && relationshipPOList.size() > 0) {
            // 文章表里查是否存在文章 有既删除-----》在引用栏目的时候做了
            // 当前栏目被引用了， 根据引用了当前栏目 的栏目 一个个的将新增的文章id插入到引用文章表中
            for (ColumnReferenceRelationshipPO relationshipPO : relationshipPOList) {
                ColumnReferenceArticlePO columnReferenceArticlePO = new ColumnReferenceArticlePO();
                columnReferenceArticlePO.setCurrentColumnId(relationshipPO.getCurrentColumnId());
                columnReferenceArticlePO.setReferenceColumnId(relationshipPO.getReferenceColumnId());
                columnReferenceArticlePO.setReferenceArticleStatus(relationshipPO.getArticleStatus());
                columnReferenceArticlePO.setReferenceArticleId(article.getId());
                boolean addReferenceArticle = columnReferenceArticleService.save(columnReferenceArticlePO);
                if (!addReferenceArticle) return R.failure().msg("创建引用文章失败");
            }
        }

        ArticleCreateVO articleCreateVO = new ArticleCreateVO();
        articleCreateVO.setId(article.getId());
        return R.success().data(articleCreateVO);
    }

    private SearchArticlePO p_copyArticleToSearchArticle(ArticlePO article, String content, String seoKeywords) {
        SearchArticlePO searchArticlePO = new SearchArticlePO();
        searchArticlePO.setArticleId(String.valueOf(article.getId()));
        searchArticlePO.setArticleTitle(article.getTitle());
        searchArticlePO.setArticleContent(content);
        searchArticlePO.setArticleType(article.getType());
        searchArticlePO.setArticleOrigin(article.getOrigin());
        searchArticlePO.setArticleStatus(article.getArticleStatus());
        searchArticlePO.setSiteId(String.valueOf(article.getSiteId()));

        searchArticlePO.setColumnId(String.valueOf(article.getColumnId()));
        searchArticlePO.setColumnName(article.getColumnName());
        searchArticlePO.setColumnXPath(article.getColumnXpath());
        searchArticlePO.setAuthorName(article.getAuthor());

        searchArticlePO.setSeoKeywords(seoKeywords);
        searchArticlePO.setReleaseChannel(article.getReleaseChannel());
        searchArticlePO.setCreateTime(article.getGmtCreate());
        searchArticlePO.setReleaseTime(article.getReleaseTime());
        return searchArticlePO;
    }

    @SitePermission({UPDATE_BY_ID})
    @ApiOperation(value = "根据id编辑文章", notes = "根据id编辑文章")
    @PutMapping("/update-by-id")
    @Transactional
    public R updateById(@ApiParam(value = "id", required = true, example = "123456789") @RequestParam(required = false) Long id,
                        @ApiParam(value = "文章标题", required = true, example = "文章标题xxx") @RequestParam(required = false) String title,
                        @ApiParam(value = "文章属性(文字WEN_ZI,图片TU_PIAN,视频SHI_PIN)", required = true, example = "WEN_ZI") @RequestParam(required = false) String attribute,
                        @ApiParam(value = "文章类型(图文资讯TU_WEN_ZI_XUN,下载文件XIA_ZAI_WEN_JIAN,跳转链接TIAO_ZHUAN_LIAN_JIE,公告资讯GONG_GAO_ZI_XUN)", required = true, example = "TU_WEN_ZI_XUN") @RequestParam(required = false) String type,
                        @ApiParam(value = "发布渠道(PC,H5,API),用英文逗号隔开", required = true, example = "PC") @RequestParam(required = false) String releaseChannel,
                        @ApiParam(value = "内容(图文资讯和公告资讯此字段的内容是文字，下载文件和跳转链接此字段的内容是一个链接)", required = false, example = "文章内容") @RequestParam(required = false) String content,
                        @ApiParam(value = "来源", required = true, example = "新浪微博") @RequestParam(required = false) String origin,
                        @ApiParam(value = "作者", required = true, example = "一个作家") @RequestParam(required = false) String author,
                        @ApiParam(value = "发布时间(10位时间戳)", required = true, example = "1234567891") @RequestParam(required = false) Date releaseTime,
                        @ApiParam(value = "公告开始时间(10位时间戳)", required = false, example = "1234567891") @RequestParam(required = false) Date gmtAnnouncementStart,
                        @ApiParam(value = "公告结束时间(10位时间戳)", required = false, example = "201234567891") @RequestParam(required = false) Date gmtAnnouncementEnd,
                        @ApiParam(value = "封面图(多张使用json形式存储)", required = false, example = "[{\"fileName\":\"icon_ghhy.png\",\"fileUrl\":\"http://10.23.222.147:8888/group1/M00/00/E6/Chfek2FkZB2EC0HqAAAAAHqO59E396.png\"}]") @RequestParam(required = false) String coverListJson,
                        @ApiParam(value = "封面图类型(单图DAN_TU,多图DUO_TU,横图HENG_TU)", required = true, example = "DAN_TU") @RequestParam(required = false) String coverType,
                        @ApiParam(value = "文章摘要", required = false, example = "文章摘要xxx") @RequestParam(required = false) String summary,
                        @ApiParam(value = "排序的文章id(如果是自定义类型的，此文章要插入到一篇文章后面，传该文章id)", required = false, example = "2165236545156") @RequestParam(required = false) Long sortArticleId,
                        @ApiParam(value = "排序类型(置顶ZHI_DING,发布时间FA_BU_SHI_JIAN,自定义ZI_DING_YI)", required = false, example = "ZHI_DING") @RequestParam(required = false) String sortType,
                        @ApiParam(value = "seo标题", required = false, example = "新闻") @RequestParam(required = false) String seoTitle,
                        @ApiParam(value = "seo关键字(字符串类型用英文逗号隔开)", required = false, example = "大新闻,社会新闻") @RequestParam(required = false) String seoKeywords,
                        @ApiParam(value = "seo描述", required = false, example = "大新闻,社会新闻") @RequestParam(required = false) String seoDesc,
                        @ApiParam(value = "扩展信息", required = false, example = "[{\"fieldCode\":\"test_1\",\"fieldAliase\":\"test_122\",\"inputType\":\"text\",\"fieldName\":\"test_122\",\"isRequired\":false,\"isSearch\":false,\"defaultValue\":\"test_122\",\"maxlength\":\"255\",\"description\":\"test_122\",\"check\":true,\"isExtend\":true,\"id\":1632289118936,\"sort\":0,\"value\":\"value值\"}]") @RequestParam(required = false) String extendFieldListJason,
                        @ApiParam(value = "相关文章(Json字符串)", required = false, example = "[{\"relevantArticleId\":\"156456412\",\"relevantArticleId\":\"798564156456\"}]") @RequestParam(required = false) String articleRelevantListJson,
                        @ApiParam(value = "附件列表(Json字符串)", required = false, example = "[{\"attachmentUrl\":\"http://xxxxx.com/xxx.zip\",\"attachmentName\":\"name1\"},{\"attachmentUrl\":\"http://xxxxx.com/xxx.txt\",\"attachmentName\":\"name2\"}]") @RequestParam(required = false) String attachmentListJson,
                        @RequestAttribute("userId") Long userId) {

        if (id == null || !ValidateUtil.Number(id) || id <= 0) return R.failureRequestParam().msg("id不能为空");
        if (StringUtils.isEmpty(title)) return R.failureRequestParam().msg("文章标题不能为空");
        if (StringUtils.isEmpty(attribute)) return R.failureRequestParam().msg("文章属性不能为空");
        if (StringUtils.isEmpty(type)) return R.failureRequestParam().msg("文章类型不能为空");
        if (StringUtils.isEmpty(releaseChannel)) return R.failureRequestParam().msg("发布渠道不能为空");
        if (StringUtils.isEmpty(origin)) return R.failureRequestParam().msg("来源不能为空");
        if (StringUtils.isEmpty(author)) return R.failureRequestParam().msg("作者不能为空");
        if (null == releaseTime) return R.failureRequestParam().msg("发布时间不能为空");
        if (StringUtils.isEmpty(coverType)) return R.failureRequestParam().msg("封面图类型不能为空");
        if (StringUtils.isNotEmpty(type) && type.equals(ArticleEnum.TYPE_GONG_GAO_ZI_XUN.getValue()) && (gmtAnnouncementStart == null || gmtAnnouncementEnd == null)) {
            return R.failureRequestParam().msg("当文章类型为公告资讯时，文章的公告开始时间和公告结束时间不能为空！");
        }

        // 更新文章
        Long articleId = articleService.updateArticle(id, title, attribute, type, releaseChannel, origin, author, releaseTime, gmtAnnouncementStart, gmtAnnouncementEnd, coverListJson, coverType, summary, sortArticleId, sortType, userId);
        // 保存或更新扩展信息
        articleExtendService.saveOrUpdateArticleExtend(id, content, seoTitle, seoKeywords, seoDesc, extendFieldListJason, userId);
        // 保存或更新附件信息
        articleAttachmentService.saveOrUpdateAttachment(id, attachmentListJson, userId);
        // 保存或更新相关文章信息
        articleRelevantService.saveOrUpdateRelevent(id, articleRelevantListJson, userId);

        // 更新全文检索中的内容
        try {
            // 先删除原有的
            searchArticleService.deleteDocByArticleId(String.valueOf(id));
            // 再添加新的
            ArticlePO articlePO = articleService.getById(articleId);
            ColumnPO columnPO = columnService.getById(articlePO.getColumnId());
            if (null != columnPO) {
                articlePO.setColumnName(columnPO.getName());
                articlePO.setColumnXpath(columnPO.getXpath());
            }
            if (null == content || null == seoKeywords) {
                QueryWrapper<ArticleExtendPO> articleExtendPOQueryWrapper = new QueryWrapper<>();
                articleExtendPOQueryWrapper.select("CONTENT", "SEO_KEYWORDS");
                articleExtendPOQueryWrapper.eq("ARTICLE_ID", id);
                ArticleExtendPO one = articleExtendService.getOne(articleExtendPOQueryWrapper);
                content = one.getContent();
                seoKeywords = one.getSeoKeywords();
            }
            SearchArticlePO searchArticlePO = p_copyArticleToSearchArticle(articlePO, content, seoKeywords);
            searchArticleService.addDoc(searchArticlePO);
        } catch (Exception e) {
            e.printStackTrace();
            R.failure().msg("操作失败");
        }


        return R.success().msg("修改成功");
    }

    @SitePermission({ARTICLE_DETAIL})
    @ApiOperation(value = "根据id获取文章信息", notes = "根据id获取文章信息")
    @GetMapping("/get-by-id")
    public R<ArticleItemVO> getById(@ApiParam(value = "id", required = true, example = "123456789") @RequestParam(required = false) Long id) {

        if (null == id || !ValidateUtil.Number(id) || id < 0) return R.failureRequestParam().msg("文章id有误");

        ArticlePO articlePO = articleService.getById(id);

        // BaseInfo
        BaseInfoVO baseInfoVO = new BaseInfoVO();
        BeanUtils.copyProperties(articlePO, baseInfoVO);

        // OtherConfigVO
        OtherConfigVO otherConfigVO = new OtherConfigVO();
        otherConfigVO.setSortType(articlePO.getSortType());
        // 前一篇
        QueryWrapper<ArticlePO> articlePOQueryWrapper = new QueryWrapper<>();
        articlePOQueryWrapper.gt("SORT", articlePO.getSort());
        // 进行升序排列，最小的就在前面
        articlePOQueryWrapper.orderByAsc("SORT");
        List<ArticlePO> articlePOS = articleService.list(articlePOQueryWrapper);
        if (!ValidateUtil.isNullOrEmpty(articlePOS)) {
            ArticlePO articleLastOne = articlePOS.get(0);
            otherConfigVO.setLastArticleId(articleLastOne.getId());
            otherConfigVO.setLastArticleTitle(articleLastOne.getTitle());
            // sortArticleId
            otherConfigVO.setSortArticleId(articleLastOne.getId());
        }
        // 后一篇
        QueryWrapper<ArticlePO> articleWrapper = new QueryWrapper<>();
        articleWrapper.lt("SORT", articlePO.getSort());
        // 进行降序排列，最大的就在前面
        articleWrapper.orderByDesc("SORT");
        List<ArticlePO> articlePOList = articleService.list(articleWrapper);
        if (!ValidateUtil.isNullOrEmpty(articlePOList)) {
            ArticlePO articleNextOne = articlePOList.get(0);
            otherConfigVO.setNextArticleId(articleNextOne.getId());
            otherConfigVO.setNextArticleTitle(articleNextOne.getTitle());
        }

        // ArticleSeoVO
        ArticleSeoVO articleSeoVO = new ArticleSeoVO();
        // 根据文章id查询出文章扩展表的数据
        QueryWrapper<ArticleExtendPO> articleExtendPOQueryWrapper = new QueryWrapper<>();
        articleExtendPOQueryWrapper.eq("ARTICLE_ID", id);
        ArticleExtendPO articleExtendPO = articleExtendService.getOne(articleExtendPOQueryWrapper);
        // 设置相应的值
        articleSeoVO.setSeoTitle(articleExtendPO.getSeoTitle());
        articleSeoVO.setSeoKeywords(articleExtendPO.getSeoKeywords());
        articleSeoVO.setSeoDesc(articleExtendPO.getSeoDesc());

        // 文章基本信息下的内容
        baseInfoVO.setContent(articleExtendPO.getContent());


        // ExtendFieldListVO
        ExtendFieldListVO extendFieldListVO = new ExtendFieldListVO();
        extendFieldListVO.setExtendFieldList(articleExtendPO.getExtendFieldList());

        // List<AttachmentVO>
        ArrayList<AttachmentVO> attachmentVOList = new ArrayList<>();
        // 根据文章id查询出文章附件表的数据
        QueryWrapper<ArticleAttachmentPO> articleAttachmentPOQueryWrapper = new QueryWrapper<>();
        articleAttachmentPOQueryWrapper.eq("ARTICLE_ID", id);
        List<ArticleAttachmentPO> list = articleAttachmentService.list(articleAttachmentPOQueryWrapper);
        // 遍历集合，设值
        if (!ValidateUtil.isNullOrEmpty(list)) {
            for (ArticleAttachmentPO articleAttachmentPO : list) {
                AttachmentVO attachmentVO = new AttachmentVO();
                attachmentVO.setAttachmentUrl(articleAttachmentPO.getAttachmentUrl());
                attachmentVO.setAttachmentName(articleAttachmentPO.getAttachmentName());
                attachmentVOList.add(attachmentVO);
            }
        }

        // List<ArticleRelevantVO>
        ArrayList<ArticleRelevantVO> articleRelevantVOList = new ArrayList<>();
        // 根据文章id查询出文章相关表的数据
        QueryWrapper<ArticleRelevantPO> articleRelevantPOQueryWrapper = new QueryWrapper<>();
        articleRelevantPOQueryWrapper.eq("ARTICLE_ID", id);
        List<ArticleRelevantPO> relevantPOList = articleRelevantService.list(articleRelevantPOQueryWrapper);
        // 遍历集合
        if (!ValidateUtil.isNullOrEmpty(relevantPOList)) {
            for (ArticleRelevantPO articleRelevantPO : relevantPOList) {
                ArticleRelevantVO articleRelevantVO = new ArticleRelevantVO();
                // 设置相关文章id
                articleRelevantVO.setRelevantArticleId(articleRelevantPO.getRelevantArticleId());
                ArticlePO articlePOById = articleService.getById(articleRelevantPO.getRelevantArticleId());
                // 名字
                if (!ValidateUtil.isNullOrEmpty(articlePOById))
                    articleRelevantVO.setRelevantArticleTitle(articlePOById.getTitle());
                articleRelevantVOList.add(articleRelevantVO);
            }
        }

        // 结果封装
        ArticleItemVO articleItemVO = new ArticleItemVO();
        articleItemVO.setBaseInfo(baseInfoVO);
        articleItemVO.setOtherConfig(otherConfigVO);
        articleItemVO.setArticleSeo(articleSeoVO);
        articleItemVO.setExtendFieldList(extendFieldListVO);
        articleItemVO.setAttachmentList(attachmentVOList);
        articleItemVO.setArticleRelevantList(articleRelevantVOList);
        return R.success().data(articleItemVO);
    }

    @SitePermission({ARTICLE_PAGE})
    @ApiOperation(value = "文章分页列表展示与搜索", notes = "文章分页列表展示与搜索")
    @GetMapping("/page-search-list")
    public R<ArticlePageListVO> pageSearchList(@ApiParam(value = "站点id(如果查询站点下的文章，则栏目id传0)", required = true, example = "123456789") @RequestParam(required = false) Long siteId,
                                               @ApiParam(value = "操作人", required = false, example = "张三") @RequestParam(required = false) String modifierName,
                                               @ApiParam(value = "根据更新时间搜索的开始时间（10位时间戳）", required = false, example = "1234567891") @RequestParam(required = false) Date gmtModifiedStart,
                                               @ApiParam(value = "根据更新时间搜索的结束时间（10位时间戳）", required = false, example = "1231231231") @RequestParam(required = false) Date gmtModifiedEnd,
                                               @ApiParam(value = "要访问的页码", required = true, example = "1") @RequestParam(required = false) Integer page,
                                               @ApiParam(value = "页面容量", required = true, example = "10") @RequestParam(required = false) Integer limit,
                                               @ApiParam(value = "文章类型(图文资讯TU_WEN_ZI_XUN,下载文件XIA_ZAI_WEN_JIAN,跳转链接TIAO_ZHUAN_LIAN_JIE,公告资讯GONG_GAO_ZI_XUN)", required = false, example = "TU_WEN_ZI_XUN") @RequestParam(required = false) String type,
                                               @ApiParam(value = "文章标题", required = false, example = "文章标题xxx") @RequestParam(required = false) String title,
                                               @ApiParam(value = "栏目id", required = true, example = "12312313123") @RequestParam(required = false) Long columnId,
                                               @ApiParam(value = "栏目名字", required = false, example = "关于我们") @RequestParam(required = false) String columnName,
                                               @ApiParam(value = "根据发布时间搜索的开始时间（10位时间戳）", required = false, example = "1234567891") @RequestParam(required = false) Date gmtReleaseTimeStart,
                                               @ApiParam(value = "根据发布时间搜索的结束时间（10位时间戳）", required = false, example = "1231231231") @RequestParam(required = false) Date gmtReleaseTimeEnd,
                                               @ApiParam(value = "文章状态(全部ALL,草稿CAO_GAO,待审核DAI_SHEN_HE,待修改DAI_XIU_GAI,已发布YI_FA_BU,已下架YI_XIA_JIA,已过期YI_GUO_QI,回收站为空值)", required = false, example = "YI_FA_BU") @RequestParam(required = false) String articleStatus,
                                               @ApiParam(value = "发布渠道(PC,H5,API)", required = false, example = "PC") @RequestParam(required = false) String releaseChannel) {

        if (siteId == null || !ValidateUtil.Number(siteId) || siteId <= 0)
            return R.failureRequestParam().msg("站点id不能为空");
        if (null == page || !ValidateUtil.Number(page) || page < 0) return R.failureRequestParam().msg("页码为空或格式不正确");
        if (null == limit || !ValidateUtil.Number(limit) || limit < 0)
            return R.failureRequestParam().msg("页条目数为空或格式不正确");
        if (columnId == null || !ValidateUtil.Number(columnId)) return R.failureRequestParam().msg("栏目id不能为空");

        ArticlePageListVO articlePageListVO = new ArticlePageListVO();

        // 预设返回值
        articlePageListVO.setPage(page);
        articlePageListVO.setLimit(limit);
        articlePageListVO.setTotal(0);
        articlePageListVO.setList(new ArrayList<>());

        // 从枚举类获取的集合，包含没居中所有的数据
        HashMap<String, String> articleEnumMap = ArticleEnum.getArticleEnumMap();

        // 条件构造器
        QueryWrapper<ArticlePO> articlePOQueryWrapper = new QueryWrapper<>();

        // 栏目id为0，查站点下的所有未被回收的栏目
        if (columnId.equals(0L)) {
            List<Long> columnIdBySiteId = siteColumnService.getNotRecoveryColumnIdBySiteId(siteId);
            if (ValidateUtil.isNullOrEmpty(columnIdBySiteId)) return R.success().data(articlePageListVO);
            articlePOQueryWrapper.in("COLUMN_ID", columnIdBySiteId);
        }

        // 根据更新人name查询更新人id
        List<UserPO> userPOList = null;
        if (StringUtils.isNotEmpty(modifierName)) {
            QueryWrapper<UserPO> userWrapper = new QueryWrapper<>();
            userWrapper.like("NAME", modifierName);
            userPOList = userService.list(userWrapper);
        }

        // 如果更新人ID集合不为空
        if (!ValidateUtil.isNullOrEmpty(userPOList)) {
            ArrayList<Long> userIdList = new ArrayList<>();
            for (UserPO userPO : userPOList) {
                userIdList.add(userPO.getId());
            }
            articlePOQueryWrapper.in("MODIFIER_ID", userIdList);
        }
        // 当更新人id查询结果为空，但是传入的更新人姓名不为空的时候，表示表中没有对应的操作人，直接返回空集合
        if ((userPOList == null || userPOList.size() == 0) && StringUtils.isNotEmpty(modifierName)) {
            articlePageListVO.setPage(page);
            articlePageListVO.setLimit(limit);
            articlePageListVO.setTotal(0);
            articlePageListVO.setList(new ArrayList<>());
            return R.success().data(articlePageListVO);
        }
        // 更新时间
        if (gmtModifiedStart != null) articlePOQueryWrapper.ge("GMT_MODIFIED", gmtModifiedStart);
        if (gmtModifiedEnd != null) articlePOQueryWrapper.le("GMT_MODIFIED", gmtModifiedEnd);
        // 文章类型
        if (StringUtils.isNotEmpty(type) && articleEnumMap.containsKey(type)) articlePOQueryWrapper.eq("TYPE", type);
        // 文章标题
        if (StringUtils.isNotEmpty(title)) articlePOQueryWrapper.like("TITLE", title);
        // 栏目id,不为0时，查栏目下的文章
        if (!columnId.equals(0L)) articlePOQueryWrapper.eq("COLUMN_ID", columnId);
        // 栏目名字
        if (StringUtils.isNotEmpty(columnName)) {
            QueryWrapper<ColumnPO> columnPOQueryWrapper = new QueryWrapper<>();
            columnPOQueryWrapper.like("NAME", columnName);
            List<ColumnPO> columnPOList = columnService.list(columnPOQueryWrapper);
            if (!ValidateUtil.isNullOrEmpty(columnPOList)) {
                ArrayList<Long> list = new ArrayList<>();
                for (ColumnPO columnPO : columnPOList) {
                    list.add(columnPO.getId());
                }
                articlePOQueryWrapper.in("COLUMN_ID", list);
            }
        }
        // 发布时间
        if (gmtReleaseTimeStart != null) articlePOQueryWrapper.ge("RELEASE_TIME", gmtReleaseTimeStart);
        if (gmtReleaseTimeEnd != null) articlePOQueryWrapper.le("RELEASE_TIME", gmtReleaseTimeEnd);
        // 文章状态
        if (StringUtils.isNotEmpty(articleStatus) && articleEnumMap.containsKey(articleStatus)) {
            // 如果文章状态不是ALL的话，就添加上加入的条件，如果是就跳过这个条件
            if (!articleStatus.equals(ArticleEnum.STATUS_ALL.getValue()))
                articlePOQueryWrapper.eq("ARTICLE_STATUS", articleStatus);
            // 查询未被回收的
            articlePOQueryWrapper.eq("IS_RECOVERY", 0);
        } else {
            // 为空的时候就查询回收站的。
            articlePOQueryWrapper.eq("IS_RECOVERY", 1);
        }
        // 发布渠道
        if (StringUtils.isNotEmpty(releaseChannel) && articleEnumMap.containsKey(releaseChannel)) {
            articlePOQueryWrapper.like("RELEASE_CHANNEL", releaseChannel);
        }

        // 排序
        articlePOQueryWrapper.orderByDesc("SORT").orderByAsc("GMT_MODIFIED");

        // 查询并封装返回结果
//        Page<ArticlePO> articlePOPage = articleService.page(new Page<>(page, limit), articlePOQueryWrapper);
        Page<ArticlePO> articlePOPage = articleService.getReferenceArticle(new Page<>(page, limit), articlePOQueryWrapper);
        articlePageListVO.setTotal((int) articlePOPage.getTotal());
        articlePageListVO.setPage((int) articlePOPage.getCurrent());
        articlePageListVO.setLimit((int) articlePOPage.getSize());
        articlePageListVO.setList(new ArrayList<>());

        List<ArticlePO> records = articlePOPage.getRecords();
        // 如果集合不为空
        if (!ValidateUtil.isNullOrEmpty(records)) {
            ArrayList<ArticleVO> articleVOList = new ArrayList<>();
            for (ArticlePO articlePO : records) {
                ArticleVO articleVO = new ArticleVO();
                BeanUtils.copyProperties(articlePO, articleVO);
                // 操作人
                UserPO userPO = userService.getById(articlePO.getModifierId());
                if (!ValidateUtil.isNullOrEmpty(userPO)) {
                    articleVO.setModifierName(userPO.getName());
                }
                // 所属栏目
                ColumnPO columnPO = columnService.getById(articlePO.getColumnId());
                if (!ValidateUtil.isNullOrEmpty(columnPO)) {
                    articleVO.setColumnName(columnPO.getName());
                }
                articleVOList.add(articleVO);
            }
            articlePageListVO.setList(articleVOList);
        }

        return R.success().data(articlePageListVO);
    }

    @SitePermission({REMOVE_BY_ID})
    @ApiOperation(value = "根据id回收文章", notes = "根据id回收文章")
    @PutMapping("/remove-by-id")
    public R removeById(@ApiParam(value = "id（文章id）", required = true, example = "12312313123") @RequestParam(required = false) Long id,
                        @RequestAttribute("userId") Long userId) {

        // 校验id
        if (id == null || !ValidateUtil.Number(id) || id <= 0) return R.failureRequestParam().msg("id格式不正确");

        // 先根据id去数据库查这条文章记录的状态是不是（草稿CAO_GAO,待修改DAI_XIU_GAI,已下架YI_XIA_JIA,已过期YI_GUO_QI）中的一个
        ArticlePO articleServiceById = articleService.getById(id);
        String articleStatus = articleServiceById.getArticleStatus();

        ArrayList<String> statusList = new ArrayList<>();
        statusList.add("CAO_GAO");
        statusList.add("DAI_XIU_GAI");
        statusList.add("YI_XIA_JIA");
        statusList.add("YI_GUO_QI");
        boolean result = false;
        if (statusList.contains(articleStatus)) {
            ArticlePO articlePO = new ArticlePO();
            articlePO.setId(id);
            articlePO.setModifierId(userId);
            articlePO.setRecovery(1);
            result = articleService.updateById(articlePO);

            try {
                searchArticleService.deleteDocByArticleId(String.valueOf(id));
            } catch (Exception e) {
                e.printStackTrace();
                return R.failure().msg("操作失败");
            }
        }
        if (result) {
            return R.success();
        } else {
            return R.failure();
        }
    }

    @SitePermission({REMOVE_BY_IDS})
    @ApiOperation(value = "根据id批量回收文章", notes = "根据id批量回收文章")
    @PutMapping("/remove-by-ids")
    public R removeByIds(@ApiParam(value = "站点id之间用英文逗号分隔", required = true, example = "12312313123,12312313123") @RequestParam(required = false) String ids,
                         @RequestAttribute("userId") Long userId) {

        // 校验ids
        if (null == ids || StringUtils.isEmpty(ids)) return R.failureRequestParam().msg("请选择你要批量回收的文章id");

        // 将字符串ids进行分割成多个字符串数组idSplit
        String[] idSplit = ids.split(",");
        // 创建一个数组存放idList
        ArrayList<Long> idList = new ArrayList<>();
        // 对字符串数组idSplit循环遍历和转换 因为传进来的id是Long类型的 此时的id是String类型的
        for (String idString : idSplit) {
            Long id = Long.valueOf(idString);
            idList.add(id);
        }

        ArrayList<String> statusList = new ArrayList<>();
        statusList.add(ArticleEnum.STATUS_CAO_GAO.getValue());
        statusList.add(ArticleEnum.STATUS_DAI_XIU_GAI.getValue());
        statusList.add(ArticleEnum.STATUS_YI_XIA_JIA.getValue());
        statusList.add(ArticleEnum.STATUS_YI_GUO_QI.getValue());

        // 根据idList 构造条件
        QueryWrapper<ArticlePO> articlePOQueryWrapper = new QueryWrapper<>();
        // 先判断id是不是在这个范围内
        articlePOQueryWrapper.in("ID", idList);
        // 然后判断状态不在要回收的范围内    在状态内就回收/不在状态内就不能回收
        articlePOQueryWrapper.notIn("ARTICLE_STATUS", statusList);
        // count==>根据 Wrapper 条件，查询符合条件的总记录数 条件判断的是：不在回收范围内的数据
        int count = articleService.count(articlePOQueryWrapper);
        // count>0说明有最少一条不符合回收条件的数据-->失败
        if (count > 0) return R.failure().msg("批量回收失败");

        // count<=0有符合回收条件的数据
        // 通过改造更新的条件构造器进行批量操作
        ArticlePO articlePO = new ArticlePO();
        UpdateWrapper<ArticlePO> articlePOUpdateWrapper = new UpdateWrapper<>();
        articlePOUpdateWrapper.set("MODIFIER_ID", userId);
        articlePOUpdateWrapper.set("IS_RECOVERY", 1);
        articlePOUpdateWrapper.in("ID", idList);

        boolean result = articleService.update(articlePO, articlePOUpdateWrapper);

        // 从检索中移除
        ArrayList<String> stringArrayList = new ArrayList<>();
        for (Long aLong : idList) {
            stringArrayList.add(String.valueOf(aLong));
        }
        try {
            searchArticleService.deleteDocBatchByArticleIds(stringArrayList);
        } catch (Exception e) {
            e.printStackTrace();
            R.failure().msg("操作失败");
        }


        if (result) return R.success().msg("批量回收成功");
        return R.failure().msg("批量回收失败");
    }

    @SitePermission({RECOVERY_BY_ID})
    @ApiOperation(value = "根据id恢复文章", notes = "根据id恢复文章")
    @PutMapping("/recovery-by-id")
    public R recoveryById(@ApiParam(value = "id", required = true, example = "12312313123") @RequestParam(required = false) Long id,
                          @RequestAttribute("userId") Long userId) {

        // 校验id
        if (id == null || !ValidateUtil.Number(id) || id <= 0) return R.failure().msg("id格式不正确");

        // 执行恢复操作 0默认 1回收
        ArticlePO articlePO = new ArticlePO();
        articlePO.setModifierId(userId);
        articlePO.setId(id);
        articlePO.setRecovery(0);
        boolean result = articleService.updateById(articlePO);

        // 添加到索引中
        articlePO = articleService.getById(id);
        ColumnPO columnPO = columnService.getById(articlePO.getColumnId());
        articlePO.setColumnName(columnPO.getName());
        articlePO.setColumnXpath(columnPO.getXpath());
        QueryWrapper<ArticleExtendPO> articleExtendPOQueryWrapper = new QueryWrapper<>();
        articleExtendPOQueryWrapper.select("CONTENT", "SEO_KEYWORDS");
        articleExtendPOQueryWrapper.eq("ARTICLE_ID", id);
        ArticleExtendPO one = articleExtendService.getOne(articleExtendPOQueryWrapper);
        SearchArticlePO searchArticlePO = p_copyArticleToSearchArticle(articlePO, one.getContent(), one.getSeoKeywords());
        try {
            searchArticleService.addDoc(searchArticlePO);
        } catch (Exception e) {
            e.printStackTrace();
            return R.failure().msg("操作失败");
        }

        if (result) return R.success().msg("恢复成功");
        return R.failure().msg("恢复失败");
    }

    @SitePermission({RECOVERY_BY_IDS})
    @ApiOperation(value = "根据id批量恢复文章", notes = "根据id批量恢复文章")
    @PutMapping("/recovery-by-ids")
    public R recoveryByIds(@ApiParam(value = "文章id之间用英文逗号分隔", required = true, example = "12312313123,12312313123") @RequestParam(required = false) String ids,
                           @RequestAttribute("userId") Long userId) {

        // 校验ids
        if (null == ids || StringUtils.isEmpty(ids)) return R.failureRequestParam().msg("请选择你要恢复的文章id");
        // 先把字符串ids分割成数组idSplit
        String[] idSplit = ids.split(",");
        // 因为id是Long类型的 所以创建一个数组存放
        ArrayList<Long> idList = new ArrayList<>();
        // 对idSplit进行遍历 idSplit转换成Long类型的 添加到idList中
        for (String idString : idSplit) {
            Long id = Long.valueOf(idString);
            idList.add(id);
        }

        // 执行恢复操作
        ArticlePO articlePO = new ArticlePO();
        UpdateWrapper<ArticlePO> articlePOUpdateWrapper = new UpdateWrapper<>();
        articlePOUpdateWrapper.in("ID", idList);
        articlePOUpdateWrapper.set("MODIFIER_ID", userId);
        articlePOUpdateWrapper.set("IS_RECOVERY", 0);
        boolean result = articleService.update(articlePO, articlePOUpdateWrapper);

        // 添加到全文检索中
        List<ArticlePO> articlePOList = articleService.listByIds(idList);
        QueryWrapper<ArticleExtendPO> articleExtendPOQueryWrapper = new QueryWrapper<>();
        articleExtendPOQueryWrapper.select("ARTICLE_ID", "CONTENT", "SEO_KEYWORDS");
        articleExtendPOQueryWrapper.in("ARTICLE_ID", idList);
        List<ArticleExtendPO> articleExtendPOList = articleExtendService.list(articleExtendPOQueryWrapper);

        // 查询文章所属栏目的集合
        ArrayList<Long> columnIdList = new ArrayList<>();
        for (ArticlePO article : articlePOList) {
            columnIdList.add(article.getColumnId());
        }
        List<ColumnPO> columnPOList = columnService.listByIds(columnIdList);

        ArrayList<SearchArticlePO> searchArticlePOS = new ArrayList<>();
        SearchArticlePO searchArticlePO;
        for (ArticlePO article : articlePOList) {
            // 如果栏目为空或者栏目id和文章的所属栏目id不相同，则查询并更改
            for (ColumnPO columnPO : columnPOList) {
                if (columnPO.getId().equals(article.getColumnId())) {
                    article.setColumnName(columnPO.getName());
                    article.setColumnXpath(columnPO.getXpath());
                }
            }
            for (ArticleExtendPO articleExtendPO : articleExtendPOList) {
                if (article.getId().equals(articleExtendPO.getArticleId())) {
                    searchArticlePO = p_copyArticleToSearchArticle(articlePO, articleExtendPO.getContent(), articleExtendPO.getSeoKeywords());
                    searchArticlePOS.add(searchArticlePO);
                    break;
                }
            }
        }
        try {
            searchArticleService.addDocBatch(searchArticlePOS);
        } catch (Exception e) {
            e.printStackTrace();
            return R.failure().msg("操作失败");
        }

        if (result) return R.success().msg("批量恢复成功");
        return R.failure().msg("批量恢复失败");
    }

    @SitePermission({RELEASE_BY_ID})
    @ApiOperation(value = "根据id发布文章", notes = "根据id发布文章")
    @PutMapping("/release-by-id")
    public R<ArticleStatusVO> releaseById(@ApiParam(value = "id", required = true, example = "12312313123") @RequestParam(required = false) Long id,
                                          @ApiParam(value = "站点id(如果查询站点下的文章，则栏目id传0)", required = true, example = "123456789") @RequestParam(required = false) Long siteId,
                                          @ApiParam(value = "当前栏目id", required = true, example = "12312313123") @RequestParam(required = false) Long columnId,
                                          @RequestAttribute("userId") Long userId) {

        // 校验id
        if (id == null || !ValidateUtil.Number(id) || id <= 0) return R.failure().msg("id格式不正确");
        if (siteId == null || !ValidateUtil.Number(siteId) || siteId <= 0)
            return R.failureRequestParam().msg("站点id不能为空");
        if (columnId == null || !ValidateUtil.Number(columnId)) return R.failureRequestParam().msg("栏目id不能为空");

        // 文章状态为(草稿CAO_GAO,待修改DAI_XIU_GAI,已下架YI_XIA_JIA,) --> 已发布YI_FA_BU,
        ArrayList<String> statusList = new ArrayList<>();
        statusList.add(ArticleEnum.STATUS_CAO_GAO.getValue());
        statusList.add(ArticleEnum.STATUS_DAI_XIU_GAI.getValue());
        statusList.add(ArticleEnum.STATUS_YI_XIA_JIA.getValue());

        // 引用的文章按照当前栏目看需不需要审核
        // 根据文章id去文章表查找当前文章的所属栏目
        ArticlePO articleById = articleService.getById(id);
        // 根据当前文章和文章的栏目以及当前栏目id 去 引用文章表 中查是否存在
        QueryWrapper<ColumnReferenceArticlePO> referenceArticlePOQueryWrapper = new QueryWrapper<>();
        referenceArticlePOQueryWrapper.eq("REFERENCE_ARTICLE_ID", articleById.getId());
        referenceArticlePOQueryWrapper.eq("REFERENCE_COLUMN_ID", articleById.getColumnId());
        referenceArticlePOQueryWrapper.eq("CURRENT_COLUMN_ID", columnId);
        ColumnReferenceArticlePO columnReferenceArticlePO = columnReferenceArticleService.getOne(referenceArticlePOQueryWrapper);
        // 不为空就说明是引用文章 去引用文章表中修改
        if (null != columnReferenceArticlePO) {
            // 判断引用文章的状态是否包含statusList
            if (statusList.contains(columnReferenceArticlePO.getReferenceArticleStatus())) {
                // 判断当前栏目审核状态-->是否需要审核(0不需要,1需要审核)   文章状态改为 待审核DAI_SHEN_HE
                ColumnPO columnPO = columnService.getById(columnId);
                ColumnReferenceArticlePO referenceArticlePO = new ColumnReferenceArticlePO();
                UpdateWrapper<ColumnReferenceArticlePO> updateWrapper = new UpdateWrapper<>();
                if (1 == columnPO.getVerifyStatus()) {
                    updateWrapper.eq("REFERENCE_ARTICLE_ID", columnReferenceArticlePO.getReferenceArticleId());
                    updateWrapper.eq("CURRENT_COLUMN_ID", columnId);
                    updateWrapper.eq("REFERENCE_COLUMN_ID", columnReferenceArticlePO.getReferenceColumnId());
                    referenceArticlePO.setReferenceArticleStatus(ArticleEnum.STATUS_DAI_SHEN_HE.getValue());
                } else {
                    // 不需要审核   已发布YI_FA_BU
                    updateWrapper.eq("REFERENCE_ARTICLE_ID", columnReferenceArticlePO.getReferenceArticleId());
                    updateWrapper.eq("CURRENT_COLUMN_ID", columnId);
                    updateWrapper.eq("REFERENCE_COLUMN_ID", columnReferenceArticlePO.getReferenceColumnId());
                    referenceArticlePO.setReferenceArticleStatus(ArticleEnum.STATUS_YI_FA_BU.getValue());
                }
                boolean update = columnReferenceArticleService.update(referenceArticlePO, updateWrapper);
                ArticleStatusVO articleStatusVO = new ArticleStatusVO();
                articleStatusVO.setStatus(referenceArticlePO.getReferenceArticleStatus());
                if (update) return R.success().data(articleStatusVO);
            } else {
                return R.failure().msg("文章类型不属于可发布类型之中");
            }
        } else {
            // 为空就去文章表中修改
            if (statusList.contains(articleById.getArticleStatus())) {
                // 根据ColumnId得到 栏目审核状态-->是否需要审核(0不需要,1需要审核)
                ColumnPO columnPO = columnService.getById(columnId);
                ArticlePO articlePO = new ArticlePO();
                // VerifyStatus=1-》栏目需要审核--》文章状态改为 待审核DAI_SHEN_HE
                if (1 == columnPO.getVerifyStatus()) {
                    articlePO.setArticleStatus(ArticleEnum.STATUS_DAI_SHEN_HE.getValue());
                } else {
                    // 栏目不需要审核--》文章状态改为 已发布YI_FA_BU
                    articlePO.setArticleStatus(ArticleEnum.STATUS_YI_FA_BU.getValue());
                }
                articlePO.setId(id);
                articlePO.setModifierId(userId);
                boolean result = articleService.updateById(articlePO);
                // 要返回的VO
                ArticleStatusVO articleStatusVO = new ArticleStatusVO();
                articleStatusVO.setStatus(articlePO.getArticleStatus());
                if (result) return R.success().data(articleStatusVO);
            } else {
                return R.failure().msg("文章类型不属于可发布类型之中");
            }
        }

        return R.failure().msg("操作失败");
    }

    @SitePermission({RELEASE_BY_IDS})
    @ApiOperation(value = "根据id批量发布文章", notes = "根据id批量发布文章")
    @PutMapping("/release-by-ids")
    public R releaseByIds(@ApiParam(value = "文章id之间用英文逗号分隔", required = true, example = "12312313123,12312313123") @RequestParam(required = false) String ids,
                          @ApiParam(value = "站点id(如果查询站点下的文章，则栏目id传0)", required = true, example = "123456789") @RequestParam(required = false) Long siteId,
                          @ApiParam(value = "当前栏目id", required = true, example = "12312313123") @RequestParam(required = false) Long columnId,
                          @RequestAttribute("userId") Long userId) {

        if (siteId == null || !ValidateUtil.Number(siteId) || siteId <= 0)
            return R.failureRequestParam().msg("站点id不能为空");
        if (columnId == null || !ValidateUtil.Number(columnId)) return R.failureRequestParam().msg("栏目id不能为空");
        // 校验ids
        if (null == ids || StringUtils.isEmpty(ids)) return R.failureRequestParam().msg("请选择你要批量发布的文章id");
        // 先把字符串ids分割成数组idSplit
        String[] idSplit = ids.split(",");
        // 因为id是Long类型的 所以创建一个数组存放
        ArrayList<Long> idList = new ArrayList<>();
        // 对idSplit进行遍历 idSplit转换成Long类型的 添加到idList中
        for (String idString : idSplit) {
            Long id = Long.valueOf(idString);
            idList.add(id);
        }

        // 文章状态为(草稿CAO_GAO,待修改DAI_XIU_GAI,已下架YI_XIA_JIA,) --> 已发布YI_FA_BU,
        ArrayList<String> statusList = new ArrayList<>();
        statusList.add(ArticleEnum.STATUS_CAO_GAO.getValue());
        statusList.add(ArticleEnum.STATUS_DAI_XIU_GAI.getValue());
        statusList.add(ArticleEnum.STATUS_YI_XIA_JIA.getValue());

        // 查询id在范围内的所有对象集合
        QueryWrapper<ArticlePO> articlePOQueryWrapper = new QueryWrapper<>();
        articlePOQueryWrapper.in("ID", idList);
        List<ArticlePO> articlePOList = articleService.list(articlePOQueryWrapper);

        // 查当前栏目的审核状态
        ColumnPO columnPO = columnService.getById(columnId);
        Integer columnVerifyStatus = columnPO.getVerifyStatus();

        // 定义更新数据的集合
        List<ArticlePO> updateArticlePOList = new ArrayList<>();

        ArticleStatusVO articleStatusVO = new ArticleStatusVO();
        ArticlePO updateArticlePO = new ArticlePO();
        // 批量发布-》1、先发布属于当前栏目的文章(文章表)  2、如果不属于当前栏目的，就去引用表中查，修改引用表中的状态
        // 这样会存在一个问题：根据直系文章的状态判断状态，主文章属于则引用文章也会变化，只有引用文章属于则不行
        if (articlePOList.size() > 0) {
            for (ArticlePO articlePO : articlePOList) {
                // 判断当前文章是否属于当前栏目
                if (columnId.equals(articlePO.getColumnId())) {
                    // 判断文章状态是否属于list  属于
                    if (statusList.contains(articlePO.getArticleStatus())) {
                        // 判断当前栏目需不需要审核(0不需要,1需要审核)  ->直接修改文章表
                        if (1 == columnVerifyStatus) {
                            updateArticlePO.setArticleStatus(ArticleEnum.STATUS_DAI_SHEN_HE.getValue());
                        } else {
                            updateArticlePO.setArticleStatus(ArticleEnum.STATUS_YI_FA_BU.getValue());
                        }
                        updateArticlePO.setId(articlePO.getId());
                        updateArticlePO.setModifierId(userId);
                        updateArticlePOList.add(updateArticlePO);
                        articleStatusVO.setStatus(updateArticlePO.getArticleStatus());
                        boolean result = articleService.updateBatchById(updateArticlePOList);
                        if (!result) return R.failure().msg("操作失败！");
                    } else {
                        // 不属于
                        return R.failure().msg("文章类型不属于可发布类型之中");
                    }
                } else {
                    // 不属于当前栏目->去引用文章表中查 修改状态
                    QueryWrapper<ColumnReferenceArticlePO> referenceArticlePOQueryWrapper = new QueryWrapper<>();
                    referenceArticlePOQueryWrapper.eq("REFERENCE_ARTICLE_ID", articlePO.getId());
                    referenceArticlePOQueryWrapper.eq("REFERENCE_COLUMN_ID", articlePO.getColumnId());
                    referenceArticlePOQueryWrapper.eq("CURRENT_COLUMN_ID", columnId);
                    ColumnReferenceArticlePO columnReferenceArticlePO = columnReferenceArticleService.getOne(referenceArticlePOQueryWrapper);

                    ColumnReferenceArticlePO referenceArticlePO = new ColumnReferenceArticlePO();
                    UpdateWrapper<ColumnReferenceArticlePO> updateWrapper = new UpdateWrapper<>();
                    // 判断引用文章表中的状态是否属于list
                    if (statusList.contains(columnReferenceArticlePO.getReferenceArticleStatus())) {
                        // 属于 判断当前栏目是否需要审核 需要->修改状态
                        if (1 == columnVerifyStatus) {
                            updateWrapper.eq("REFERENCE_ARTICLE_ID", columnReferenceArticlePO.getReferenceArticleId());
                            updateWrapper.eq("CURRENT_COLUMN_ID", columnId);
                            updateWrapper.eq("REFERENCE_COLUMN_ID", columnReferenceArticlePO.getReferenceColumnId());
                            referenceArticlePO.setReferenceArticleStatus(ArticleEnum.STATUS_DAI_SHEN_HE.getValue());
                        } else {
                            // 不需要审核   已发布YI_FA_BU
                            updateWrapper.eq("REFERENCE_ARTICLE_ID", columnReferenceArticlePO.getReferenceArticleId());
                            updateWrapper.eq("CURRENT_COLUMN_ID", columnId);
                            updateWrapper.eq("REFERENCE_COLUMN_ID", columnReferenceArticlePO.getReferenceColumnId());
                            referenceArticlePO.setReferenceArticleStatus(ArticleEnum.STATUS_YI_FA_BU.getValue());
                        }
                        boolean update = columnReferenceArticleService.update(referenceArticlePO, updateWrapper);
                        if (!update) return R.failure().msg("操作失败！");
                    } else {
                        // 不属于
                        return R.failure().msg("引用文章类型不属于可发布类型之中");
                    }
                }
/*
                // 判断当前文章是否符合statusList 如果不符合就false
                if (!statusList.contains(articlePO.getArticleStatus())) return R.failure().msg("文章类型不属于可发布类型之中");
                // 符合则开始更新
                ArticlePO updateArticlePO = new ArticlePO();
                Long id = articlePO.getId();
                Long articlePOColumnId = articlePO.getColumnId();
                // 根据ColumnId获取栏目信息 得到 栏目审核状态-->是否需要审核(0不需要,1需要审核)
                ColumnPO columnPO = columnService.getById(articlePOColumnId);
                Integer columnVerifyStatus = columnPO.getVerifyStatus();
                // 栏目需要审核--》文章状态改为待审核DAI_SHEN_HE
                if (1 == columnVerifyStatus) {
                    updateArticlePO.setArticleStatus(ArticleEnum.STATUS_DAI_SHEN_HE.getValue());
                } else { // 栏目不需要审核--》文章状态改为 已发布YI_FA_BU
                    updateArticlePO.setArticleStatus(ArticleEnum.STATUS_YI_FA_BU.getValue());
                }
                updateArticlePO.setId(id);
                updateArticlePO.setModifierId(userId);
                updateArticlePOList.add(updateArticlePO);

                articleStatusVO.setStatus(updateArticlePO.getArticleStatus());*/
            }
        }
        return R.success().msg("操作成功");
    }

    @SitePermission({ARTICLE_COPY_BY_ID})
    @ApiOperation(value = "根据id复制文章", notes = "根据id复制文章")
    @PostMapping("/article-copy-by-id")
    @Transactional
    public R<ArticleStatusVO> articleCopyById(@ApiParam(value = "id", required = true, example = "12312313123") @RequestParam(required = false) Long id,
                                              @ApiParam(value = "站点id(如果查询站点下的文章，则栏目id传0)", required = true, example = "123456789") @RequestParam(required = false) Long siteId,
                                              @ApiParam(value = "当前栏目id", required = true, example = "12312313123") @RequestParam(required = false) Long columnId,
                                              @RequestAttribute("userId") Long userId) {
        // 校验id
        if (id == null || !ValidateUtil.Number(id) || id <= 0) return R.failure().msg("id格式不正确");
        if (siteId == null || !ValidateUtil.Number(siteId) || siteId <= 0)
            return R.failureRequestParam().msg("站点id不能为空");
        if (columnId == null || !ValidateUtil.Number(columnId)) return R.failureRequestParam().msg("栏目id不能为空");

        // 1、 查询出id对应的数据
        Boolean result = p_copyArticle(id, userId, columnId);
        ArticleStatusVO articleStatusVO = new ArticleStatusVO();
        articleStatusVO.setStatus(ArticleEnum.STATUS_CAO_GAO.getValue());
        return result ? R.success().msg("复制成功").data(articleStatusVO) : R.failure().msg("复制失败");
    }

    // 加了引用栏目复制的方法->其实就是将原来文章的栏目id换成当前传进来的columnId
    private Boolean p_copyArticle(long id, Long userId, Long columnId) {
        ArticlePO articleOriginalPO = articleService.getById(id);
        String copyTitle = "[复制]-" + articleOriginalPO.getTitle();

        ArticlePO articlePO = articleService.saveArticle(articleOriginalPO.getSiteId(), columnId, copyTitle, articleOriginalPO.getAttribute(), articleOriginalPO.getType(), articleOriginalPO.getReleaseChannel(),
                articleOriginalPO.getOrigin(), articleOriginalPO.getAuthor(), articleOriginalPO.getReleaseTime(), articleOriginalPO.getGmtAnnouncementStart(), articleOriginalPO.getGmtAnnouncementEnd(),
                articleOriginalPO.getCover(), articleOriginalPO.getCoverType(), articleOriginalPO.getSummary(), articleOriginalPO.getId(), articleOriginalPO.getSortType(), userId);
        if (null == articlePO.getId()) return false;
        // 2、查询出文章id对应的扩展表的信息
        QueryWrapper<ArticleExtendPO> articleExtendPOQueryWrapper = new QueryWrapper<>();
        articleExtendPOQueryWrapper.eq("ARTICLE_ID", id);
        ArticleExtendPO articleExtendPO = articleExtendService.getOne(articleExtendPOQueryWrapper);
        // 复制扩展表信息
        if (!ValidateUtil.isNullOrEmpty(articleExtendPO)) {
            articleExtendService.saveOrUpdateArticleExtend(articlePO.getId(), articleExtendPO.getContent(), articleExtendPO.getSeoTitle(),
                    articleExtendPO.getSeoKeywords(), articleExtendPO.getSeoDesc(), articleExtendPO.getExtendFieldList(), userId);
        }
        // 获取附件信息
        QueryWrapper<ArticleAttachmentPO> articleAttachmentPOQueryWrapper = new QueryWrapper<>();
        articleAttachmentPOQueryWrapper.eq("ARTICLE_ID", id);
        List<ArticleAttachmentPO> articleAttachmentPOList = articleAttachmentService.list(articleAttachmentPOQueryWrapper);
        // 复制附件信息
        if (!ValidateUtil.isNullOrEmpty(articleAttachmentPOList)) {

            ArrayList<AttachmentVO> attachmentVOList = new ArrayList<>();
            articleAttachmentPOList.forEach(articleAttachmentPO -> {
                AttachmentVO attachmentVO = new AttachmentVO();
                attachmentVO.setAttachmentUrl(articleAttachmentPO.getAttachmentUrl());
                attachmentVO.setAttachmentName(articleAttachmentPO.getAttachmentUrl());
                attachmentVOList.add(attachmentVO);
            });
            String attachmentJson = JSON.toJSONString(attachmentVOList);
            // 进行添加
            articleAttachmentService.saveOrUpdateAttachment(articlePO.getId(), attachmentJson, userId);
        }
        // 获取相关文章信息
        QueryWrapper<ArticleRelevantPO> articleRelevantPOQueryWrapper = new QueryWrapper<>();
        articleRelevantPOQueryWrapper.eq("ARTICLE_ID", id);
        List<ArticleRelevantPO> RelevantPOList = articleRelevantService.list(articleRelevantPOQueryWrapper);
        // 复制相关文章信息
        if (!ValidateUtil.isNullOrEmpty(RelevantPOList)) {
            ArrayList<ArticleRelevantVO> articleRelevantVOS = new ArrayList<>();
            for (ArticleRelevantPO articleRelevantPO : RelevantPOList) {
                ArticleRelevantVO relevantVO = new ArticleRelevantVO();
                relevantVO.setRelevantArticleId(articleRelevantPO.getRelevantArticleId());
                articleRelevantVOS.add(relevantVO);
            }
            String relevantJson = JSON.toJSONString(articleRelevantVOS);
            articleRelevantService.saveOrUpdateRelevent(articlePO.getId(), relevantJson, userId);

        }
        return true;
    }


    @SitePermission({ARTICLE_COPY_BY_IDS})
    @ApiOperation(value = "根据id批量复制文章", notes = "根据id批量复制文章")
    @PostMapping("/article-copy-by-ids")
    @Transactional
    public R<ArticleStatusVO> articleCopyByIds(@ApiParam(value = "文章id之间用英文逗号分隔", required = true, example = "12312313123,12312313123") @RequestParam(required = false) String ids,
                                               @ApiParam(value = "站点id(如果查询站点下的文章，则栏目id传0)", required = true, example = "123456789") @RequestParam(required = false) Long siteId,
                                               @ApiParam(value = "当前栏目id", required = true, example = "12312313123") @RequestParam(required = false) Long columnId,
                                               @RequestAttribute("userId") Long userId) {
        // 校验ids
        if (null == ids || StringUtils.isEmpty(ids)) return R.failureRequestParam().msg("请选择你要复制的文章id");

        // 先把字符串ids分割成数组idSplit
        String[] idSplit = ids.split(",");
        // 因为id是Long类型的 所以创建一个数组存放
        ArrayList<Long> idList = new ArrayList<>();
        // 对idSplit进行遍历 idSplit转换成Long类型的 添加到idList中
        for (String idString : idSplit) {
            Long id = Long.valueOf(idString);
            idList.add(id);
        }

        // 进行批量添加
        for (Long id : idList) {
            p_copyArticle(id, userId, columnId);
        }

        ArticleStatusVO articleStatusVO = new ArticleStatusVO();
        articleStatusVO.setStatus(ArticleEnum.STATUS_CAO_GAO.getValue());
        return R.success().msg("批量复制成功").data(articleStatusVO);
    }

    @SitePermission({VERIFY_BY_ID})
    @ApiOperation(value = "根据id审核文章", notes = "根据id审核文章")
    @PutMapping("/verify-by-id")
    public R<ArticleStatusVO> verifyById(@ApiParam(value = "id", required = true, example = "12312313123") @RequestParam(required = false) Long id,
                                         @ApiParam(value = "审核状态(0拒绝,1通过)", required = true, example = "1") @RequestParam(required = false) Long verifyStatus,
                                         @ApiParam(value = "审核原因(1通过选填,0拒绝必填)", required = false, example = "拒绝需要理由") @RequestParam(required = false) String verifyReason,
                                         @ApiParam(value = "站点id(如果查询站点下的文章，则栏目id传0)", required = true, example = "123456789") @RequestParam(required = false) Long siteId,
                                         @ApiParam(value = "当前栏目id", required = true, example = "12312313123") @RequestParam(required = false) Long columnId,
                                         @RequestAttribute("userId") Long userId) {

        // 校验id
        if (id == null || !ValidateUtil.Number(id) || id <= 0) return R.failure().msg("id格式不正确");
        if (verifyStatus == null || !ValidateUtil.Number(verifyStatus) || verifyStatus < 0)
            return R.failure().msg("审核状态格式不正确");
        if (siteId == null || !ValidateUtil.Number(siteId) || siteId <= 0)
            return R.failureRequestParam().msg("站点id不能为空");
        if (columnId == null || !ValidateUtil.Number(columnId)) return R.failureRequestParam().msg("栏目id不能为空");

        // 根据文章id去文章表查文章的信息
        ArticlePO articleById = articleService.getById(id);
        // 根据当前文章和文章的栏目以及当前栏目id 去 引用文章表 中查是否存在
        QueryWrapper<ColumnReferenceArticlePO> referenceArticlePOQueryWrapper = new QueryWrapper<>();
        referenceArticlePOQueryWrapper.eq("REFERENCE_ARTICLE_ID", articleById.getId());
        referenceArticlePOQueryWrapper.eq("REFERENCE_COLUMN_ID", articleById.getColumnId());
        referenceArticlePOQueryWrapper.eq("CURRENT_COLUMN_ID", columnId);
        ColumnReferenceArticlePO columnReferenceArticlePO = columnReferenceArticleService.getOne(referenceArticlePOQueryWrapper);
        // 不为空就说明是引用文章 去引用文章表中修改
        if (null != columnReferenceArticlePO) {
            // 状态校验，只有待审核的可以进行审核操作
            if (ArticleEnum.STATUS_DAI_SHEN_HE.getValue().equals(columnReferenceArticlePO.getReferenceArticleStatus())) {
                ColumnReferenceArticlePO referenceArticlePO = new ColumnReferenceArticlePO();
                UpdateWrapper<ColumnReferenceArticlePO> updateWrapper = new UpdateWrapper<>();
                // 判断审核状态 1->发布
                if (1 == verifyStatus) {
                    updateWrapper.eq("REFERENCE_ARTICLE_ID", columnReferenceArticlePO.getReferenceArticleId());
                    updateWrapper.eq("CURRENT_COLUMN_ID", columnId);
                    updateWrapper.eq("REFERENCE_COLUMN_ID", columnReferenceArticlePO.getReferenceColumnId());
                    referenceArticlePO.setReferenceArticleStatus(ArticleEnum.STATUS_YI_FA_BU.getValue());
                } else {
                    // 0拒绝 要填理由
                    updateWrapper.eq("REFERENCE_ARTICLE_ID", columnReferenceArticlePO.getReferenceArticleId());
                    updateWrapper.eq("CURRENT_COLUMN_ID", columnId);
                    updateWrapper.eq("REFERENCE_COLUMN_ID", columnReferenceArticlePO.getReferenceColumnId());
                    if (StringUtils.isEmpty(verifyReason)) return R.failure().msg("拒绝原因必填");
                    referenceArticlePO.setVerifyReason(verifyReason);
                    referenceArticlePO.setReferenceArticleStatus(ArticleEnum.STATUS_DAI_XIU_GAI.getValue());
                }
                boolean update = columnReferenceArticleService.update(referenceArticlePO, updateWrapper);
                ArticleStatusVO articleStatusVO = new ArticleStatusVO();
                articleStatusVO.setStatus(referenceArticlePO.getReferenceArticleStatus());
                if (update) return R.success().data(articleStatusVO);
            } else {
                return R.failure().msg("该文章不是待审核状态无法审核");
            }
        } else {
            // 为空 去文章表修改   状态校验，只有待审核的可以进行审核操作
            if (ArticleEnum.STATUS_DAI_SHEN_HE.getValue().equals(articleById.getArticleStatus())) {
                ArticlePO articlePO = new ArticlePO();
                // 判断审核状态 1->发布
                if (1 == verifyStatus) {
                    articlePO.setArticleStatus(ArticleEnum.STATUS_YI_FA_BU.getValue());
                } else {
                    // 0拒绝 要填理由
                    articlePO.setArticleStatus(ArticleEnum.STATUS_DAI_XIU_GAI.getValue());
                    // 审核原因必填
                    if (StringUtils.isEmpty(verifyReason)) return R.failure().msg("拒绝原因必填");
                    articlePO.setVerifyReason(verifyReason);
                }
                articlePO.setId(id);
                articlePO.setModifierId(userId);
                boolean result = articleService.updateById(articlePO);
                ArticleStatusVO articleStatusVO = new ArticleStatusVO();
                articleStatusVO.setStatus(articlePO.getArticleStatus());
                if (result) return R.success().msg("操作成功").data(articleStatusVO);
            } else {
                return R.failure().msg("文章类型不属于可发布类型之中");
            }
        }
        return R.failure().msg("操作失败");
/*
        // 状态校验，只有待审核的可以进行审核操作
        ArticlePO articleById = articleService.getById(id);
        String articleStatus = articleById.getArticleStatus();
        if (!ArticleEnum.STATUS_DAI_SHEN_HE.getValue().equals(articleStatus)) return R.failure().msg("该文章不是待审核状态无法审核");

        // 更新
        ArticlePO articlePO = new ArticlePO();
        if (0 == verifyStatus) {
            // 0 拒绝-》修改文章类型为待修改DAI_XIU_GAI
            articlePO.setArticleStatus(ArticleEnum.STATUS_DAI_XIU_GAI.getValue());
            // 审核原因必填
            if (StringUtils.isEmpty(verifyReason)) return R.failure().msg("拒绝原因必填");
            articlePO.setVerifyReason(verifyReason);
        } else {
            // 1 通过-》修改文章类型为已发布YI_FA_BU
            articlePO.setArticleStatus(ArticleEnum.STATUS_YI_FA_BU.getValue());
        }
        articlePO.setId(id);
        articlePO.setModifierId(userId);

        boolean result = articleService.updateById(articlePO);

        ArticleStatusVO articleStatusVO = new ArticleStatusVO();
        articleStatusVO.setStatus(articlePO.getArticleStatus());

        if (result) return R.success().msg("操作成功").data(articleStatusVO);
        return R.failure().msg("操作失败");*/
    }

    @SitePermission({VERIFY_BY_IDS})
    @ApiOperation(value = "根据id批量审核文章", notes = "根据id批量审核文章")
    @PutMapping("/verify-by-ids")
    public R<ArticleStatusVO> verifyByIds(@ApiParam(value = "文章id之间用英文逗号分隔", required = true, example = "12312313123") @RequestParam(required = false) String ids,
                                          @ApiParam(value = "审核状态(0拒绝,1通过)", required = true, example = "1") @RequestParam(required = false) Long verifyStatus,
                                          @ApiParam(value = "审核原因(1通过选填,0拒绝必填)", required = false, example = "拒绝需要理由") @RequestParam(required = false) String verifyReason,
                                          @ApiParam(value = "站点id(如果查询站点下的文章，则栏目id传0)", required = true, example = "123456789") @RequestParam(required = false) Long siteId,
                                          @ApiParam(value = "当前栏目id", required = true, example = "12312313123") @RequestParam(required = false) Long columnId,
                                          @RequestAttribute("userId") Long userId) {

        // 校验ids
        if (null == ids || StringUtils.isEmpty(ids)) return R.failureRequestParam().msg("请选择你要审核的文章id");
        if (verifyStatus == null || !ValidateUtil.Number(verifyStatus) || verifyStatus < 0)
            return R.failure().msg("审核状态格式不正确");
        if (siteId == null || !ValidateUtil.Number(siteId) || siteId <= 0)
            return R.failureRequestParam().msg("站点id不能为空");
        if (columnId == null || !ValidateUtil.Number(columnId)) return R.failureRequestParam().msg("栏目id不能为空");

        // 先把字符串ids分割成数组idSplit
        String[] idSplit = ids.split(",");
        // 因为id是Long类型的 所以创建一个数组存放
        ArrayList<Long> idList = new ArrayList<>();
        // 对idSplit进行遍历 idSplit转换成Long类型的 添加到idList中
        for (String idString : idSplit) {
            Long id = Long.valueOf(idString);
            idList.add(id);
        }

        // 查询id在范围内的集合对象
        QueryWrapper<ArticlePO> articlePOQueryWrapper = new QueryWrapper<>();
        articlePOQueryWrapper.in("ID", idList);
        List<ArticlePO> articlePOList = articleService.list(articlePOQueryWrapper);

        ArticleStatusVO articleStatusVO = new ArticleStatusVO();

        // 定义更新的集合
        ArrayList<ArticlePO> updateArticlePOList = new ArrayList<>();

        // 批量审核-》1、先审核属于当前栏目的文章(文章表)  2、如果不属于当前栏目的，就去引用表中查，修改引用表中的状态
        // 这样会存在一个问题：根据直系文章的状态判断状态，主文章属于则引用文章也会变化，只有引用文章属于则不行
        // 判断集合里面有没有对象
        if (articlePOList.size() > 0) {
            for (ArticlePO articlePO : articlePOList) {
                // 判断当前文章是否属于当前栏目  是->修改文章表
                if (columnId.equals(articlePO.getColumnId())) {
                    // 判断文章状态是否属于待审核  属于
                    if (ArticleEnum.STATUS_DAI_SHEN_HE.getValue().equals(articlePO.getArticleStatus())) {
                        ArticlePO updateArticlePO = new ArticlePO();
                        // 判断审核状态(0拒绝,1发布)  ->直接修改文章表
                        if (1 == verifyStatus) {
                            updateArticlePO.setArticleStatus(ArticleEnum.STATUS_YI_FA_BU.getValue());
                        } else {
                            // 拒绝
                            updateArticlePO.setArticleStatus(ArticleEnum.STATUS_DAI_XIU_GAI.getValue());
                            if (StringUtils.isEmpty(verifyReason)) return R.failure().msg("拒绝原因必填");
                            updateArticlePO.setVerifyReason(verifyReason);
                        }
                        updateArticlePO.setId(articlePO.getId());
                        updateArticlePO.setModifierId(userId);
                        updateArticlePOList.add(updateArticlePO);
                        articleStatusVO.setStatus(updateArticlePO.getArticleStatus());
                        boolean result = articleService.updateBatchById(updateArticlePOList);
                        if (!result) return R.failure().msg("操作失败！");
                    } else {
                        // 不属于
                        return R.failure().msg("文章类型不属于可发布类型之中");
                    }
                } else {
                    // 不属于当前栏目->去引用文章表中查 修改状态
                    QueryWrapper<ColumnReferenceArticlePO> referenceArticlePOQueryWrapper = new QueryWrapper<>();
                    referenceArticlePOQueryWrapper.eq("REFERENCE_ARTICLE_ID", articlePO.getId());
                    referenceArticlePOQueryWrapper.eq("CURRENT_COLUMN_ID", columnId);
                    referenceArticlePOQueryWrapper.eq("REFERENCE_COLUMN_ID", articlePO.getColumnId());
                    ColumnReferenceArticlePO columnReferenceArticlePO = columnReferenceArticleService.getOne(referenceArticlePOQueryWrapper);

                    ColumnReferenceArticlePO referenceArticlePO = new ColumnReferenceArticlePO();
                    UpdateWrapper<ColumnReferenceArticlePO> updateWrapper = new UpdateWrapper<>();
                    // 判断引用文章表中的状态是否是待审核    是
                    if (ArticleEnum.STATUS_DAI_SHEN_HE.getValue().equals(columnReferenceArticlePO.getReferenceArticleStatus())) {
                        // 判断当前审核状态(0不需要,1需要审核)  ->直接修改引用文章表
                        if (1 == verifyStatus) {
                            updateWrapper.eq("REFERENCE_ARTICLE_ID", columnReferenceArticlePO.getReferenceArticleId());
                            updateWrapper.eq("CURRENT_COLUMN_ID", columnId);
                            updateWrapper.eq("REFERENCE_COLUMN_ID", columnReferenceArticlePO.getReferenceColumnId());
                            referenceArticlePO.setReferenceArticleStatus(ArticleEnum.STATUS_YI_FA_BU.getValue());
                        } else {
                            // 0拒绝 审核原因必填
                            updateWrapper.eq("REFERENCE_ARTICLE_ID", columnReferenceArticlePO.getReferenceArticleId());
                            updateWrapper.eq("CURRENT_COLUMN_ID", columnId);
                            updateWrapper.eq("REFERENCE_COLUMN_ID", columnReferenceArticlePO.getReferenceColumnId());
                            if (StringUtils.isEmpty(verifyReason)) return R.failure().msg("拒绝原因必填");
                            referenceArticlePO.setVerifyReason(verifyReason);
                            referenceArticlePO.setReferenceArticleStatus(ArticleEnum.STATUS_DAI_XIU_GAI.getValue());
                        }
                        boolean update = columnReferenceArticleService.update(referenceArticlePO, updateWrapper);
                        if (!update) return R.failure().msg("操作失败！");
                    } else {
                        // 不属于
                        return R.failure().msg("引用文章类型不属于可发布类型之中");
                    }
                }
            }
        }
        return R.success().msg("操作成功！");
    }

    @SitePermission({OFF_SHELF_BY_ID})
    @ApiOperation(value = "根据id下架文章", notes = "根据id下架文章")
    @PutMapping("/off-shelf-by-id")
    public R<ArticleStatusVO> offShelfById(@ApiParam(value = "id", required = true, example = "12312313123") @RequestParam(required = false) Long id,
                                           @ApiParam(value = "站点id(如果查询站点下的文章，则栏目id传0)", required = true, example = "123456789") @RequestParam(required = false) Long siteId,
                                           @ApiParam(value = "当前栏目id", required = true, example = "12312313123") @RequestParam(required = false) Long columnId,
                                           @RequestAttribute("userId") Long userId) {

        // 校验id
        if (id == null || !ValidateUtil.Number(id) || id <= 0) return R.failure().msg("id格式不正确");
        if (siteId == null || !ValidateUtil.Number(siteId) || siteId <= 0)
            return R.failureRequestParam().msg("站点id不能为空");
        if (columnId == null || !ValidateUtil.Number(columnId)) return R.failureRequestParam().msg("栏目id不能为空");

        // 状态校验，只有已发布的可以进行下架操作
        ArticlePO articleById = articleService.getById(id);
        // 只有已发布的可以进行下架操作
        // String articleStatus = articleById.getArticleStatus();

        // 根据当前文章和文章的栏目以及当前栏目id 去 引用文章表 中查是否存在
        QueryWrapper<ColumnReferenceArticlePO> referenceArticlePOQueryWrapper = new QueryWrapper<>();
        referenceArticlePOQueryWrapper.eq("REFERENCE_ARTICLE_ID", articleById.getId());
        referenceArticlePOQueryWrapper.eq("REFERENCE_COLUMN_ID", articleById.getColumnId());
        referenceArticlePOQueryWrapper.eq("CURRENT_COLUMN_ID", columnId);
        ColumnReferenceArticlePO columnReferenceArticlePO = columnReferenceArticleService.getOne(referenceArticlePOQueryWrapper);

        // 不为空就说明是引用文章 去引用文章表中修改
        if (null != columnReferenceArticlePO) {
            ColumnReferenceArticlePO referenceArticlePO = new ColumnReferenceArticlePO();
            UpdateWrapper<ColumnReferenceArticlePO> updateWrapper = new UpdateWrapper<>();
            if (ArticleEnum.STATUS_YI_FA_BU.getValue().equals(columnReferenceArticlePO.getReferenceArticleStatus())) {
                updateWrapper.eq("REFERENCE_ARTICLE_ID", columnReferenceArticlePO.getReferenceArticleId());
                updateWrapper.eq("CURRENT_COLUMN_ID", columnId);
                updateWrapper.eq("REFERENCE_COLUMN_ID", columnReferenceArticlePO.getReferenceColumnId());
                referenceArticlePO.setReferenceArticleStatus(ArticleEnum.STATUS_YI_XIA_JIA.getValue());
                boolean update = columnReferenceArticleService.update(referenceArticlePO, updateWrapper);
                ArticleStatusVO articleStatusVO = new ArticleStatusVO();
                articleStatusVO.setStatus(referenceArticlePO.getReferenceArticleStatus());
                if (update) return R.success().msg("操作成功").data(articleStatusVO);
            } else {
                return R.failure().msg("该文章不是已发布状态无法下架");
            }
        } else {
            // 为空 去文章表修改   状态校验，只有已发布的可以进行下架操作
            if (ArticleEnum.STATUS_YI_FA_BU.getValue().equals(articleById.getArticleStatus())) {
                ArticlePO articlePO = new ArticlePO();
                articlePO.setArticleStatus(ArticleEnum.STATUS_YI_XIA_JIA.getValue());
                articlePO.setModifierId(userId);
                articlePO.setId(id);
                boolean result = articleService.updateById(articlePO);
                ArticleStatusVO articleStatusVO = new ArticleStatusVO();
                articleStatusVO.setStatus(ArticleEnum.STATUS_YI_XIA_JIA.getValue());
                if (result) return R.success().msg("操作成功").data(articleStatusVO);
            } else {
                return R.failure().msg("该文章不是已发布状态无法下架");
            }
        }
        return R.failure().msg("操作失败");
/*
        String articleStatus = articleById.getArticleStatus();
        if (!ArticleEnum.STATUS_YI_FA_BU.getValue().equals(articleStatus)) return R.failure().msg("该文章不是已发布状态无法下架");

        // 更新
        ArticlePO articlePO = new ArticlePO();
        articlePO.setArticleStatus(ArticleEnum.STATUS_YI_XIA_JIA.getValue());
        articlePO.setModifierId(userId);
        articlePO.setId(id);

        boolean result = articleService.updateById(articlePO);
        ArticleStatusVO articleStatusVO = new ArticleStatusVO();
        articleStatusVO.setStatus(ArticleEnum.STATUS_YI_XIA_JIA.getValue());

        if (result) return R.success().msg("操作成功").data(articleStatusVO);
        return R.failure().msg("操作失败");*/
    }

    @SitePermission({OFF_SHELF_BY_IDS})
    @ApiOperation(value = "根据id批量下架文章", notes = "根据id批量下架文章")
    @PutMapping("/off-shelf-by-ids")
    public R<ArticleStatusVO> offShelfByIds(@ApiParam(value = "文章id之间用英文逗号分隔", required = true, example = "12312313123") @RequestParam(required = false) String ids,
                                            @ApiParam(value = "站点id(如果查询站点下的文章，则栏目id传0)", required = true, example = "123456789") @RequestParam(required = false) Long siteId,
                                            @ApiParam(value = "当前栏目id", required = true, example = "12312313123") @RequestParam(required = false) Long columnId,
                                            @RequestAttribute("userId") Long userId) {
        if (siteId == null || !ValidateUtil.Number(siteId) || siteId <= 0)
            return R.failureRequestParam().msg("站点id不能为空");
        if (columnId == null || !ValidateUtil.Number(columnId)) return R.failureRequestParam().msg("栏目id不能为空");
        // 校验ids
        if (null == ids || StringUtils.isEmpty(ids)) return R.failureRequestParam().msg("请选择你要下架的文章id");
        // 先把字符串ids分割成数组idSplit
        String[] idSplit = ids.split(",");
        // 因为id是Long类型的 所以创建一个数组存放
        ArrayList<Long> idList = new ArrayList<>();
        // 对idSplit进行遍历 idSplit转换成Long类型的 添加到idList中
        for (String idString : idSplit) {
            Long id = Long.valueOf(idString);
            idList.add(id);
        }

        // 查询id在范围内的集合对象
        QueryWrapper<ArticlePO> articlePOQueryWrapper = new QueryWrapper<>();
        articlePOQueryWrapper.in("ID", idList);
        List<ArticlePO> articlePOList = articleService.list(articlePOQueryWrapper);

        ArticleStatusVO articleStatusVO = new ArticleStatusVO();
        // 定义更新的集合
        ArrayList<ArticlePO> updateArticlePOList = new ArrayList<>();
        // 判断集合里面有没有对象
        if (articlePOList.size() > 0) {
            // 遍历每一个文章
            for (ArticlePO articlePO : articlePOList) {
                // 判断当前文章是否属于当前栏目  是->修改文章表
                if (columnId.equals(articlePO.getColumnId())) {
                    // 判断当前文章是否是已发布状态 是>修改文章表
                    if (ArticleEnum.STATUS_YI_FA_BU.getValue().equals(articlePO.getArticleStatus())) {
                        ArticlePO updateArticlePO = new ArticlePO();
                        updateArticlePO.setArticleStatus(ArticleEnum.STATUS_YI_XIA_JIA.getValue());
                        updateArticlePO.setId(articlePO.getId());
                        updateArticlePO.setModifierId(userId);
                        updateArticlePOList.add(updateArticlePO);
                        articleStatusVO.setStatus(updateArticlePO.getArticleStatus());
                        boolean result = articleService.updateBatchById(updateArticlePOList);
                        if (!result) return R.failure().msg("操作失败！");
                    } else {
                        // 不属于
                        return R.failure().msg("文章类型不属于可下架类型之中");
                    }
                } else {
                    // 不属于当前栏目->去引用文章表中查 修改状态
                    QueryWrapper<ColumnReferenceArticlePO> referenceArticlePOQueryWrapper = new QueryWrapper<>();
                    referenceArticlePOQueryWrapper.eq("REFERENCE_ARTICLE_ID", articlePO.getId());
                    referenceArticlePOQueryWrapper.eq("CURRENT_COLUMN_ID", columnId);
                    referenceArticlePOQueryWrapper.eq("REFERENCE_COLUMN_ID", articlePO.getColumnId());
                    ColumnReferenceArticlePO columnReferenceArticlePO = columnReferenceArticleService.getOne(referenceArticlePOQueryWrapper);

                    ColumnReferenceArticlePO referenceArticlePO = new ColumnReferenceArticlePO();
                    UpdateWrapper<ColumnReferenceArticlePO> updateWrapper = new UpdateWrapper<>();

                    // 判断当前文章是否是已发布状态 是>修改引用文章表
                    if (ArticleEnum.STATUS_YI_FA_BU.getValue().equals(columnReferenceArticlePO.getReferenceArticleStatus())) {
                        referenceArticlePO.setReferenceArticleStatus(ArticleEnum.STATUS_YI_XIA_JIA.getValue());
                        updateWrapper.eq("REFERENCE_ARTICLE_ID", columnReferenceArticlePO.getReferenceArticleId());
                        updateWrapper.eq("CURRENT_COLUMN_ID", columnId);
                        updateWrapper.eq("REFERENCE_COLUMN_ID", columnReferenceArticlePO.getReferenceColumnId());
                    } else {
                        // 不属于
                        return R.failure().msg("引用文章类型不属于可下架类型之中");
                    }
                    boolean update = columnReferenceArticleService.update(referenceArticlePO, updateWrapper);
                    if (!update) return R.failure().msg("操作失败！");
                }
            }
        }
        return R.success().msg("操作成功！");
                /*// 判断当前文章是否是已发布状态 取反
                if (!ArticleEnum.STATUS_YI_FA_BU.getValue().equals(articlePO.getArticleStatus()))
                    return R.failure().msg("选择的文章部分不是已发布状态无法下架");


                // 更新
                ArticlePO updateArticlePO = new ArticlePO();
                updateArticlePO.setArticleStatus(ArticleEnum.STATUS_YI_XIA_JIA.getValue());
                updateArticlePO.setId(articlePO.getId());
                updateArticlePO.setModifierId(userId);

                updateArticlePOList.add(updateArticlePO);
            }
        }
        boolean result = articleService.updateBatchById(updateArticlePOList);
        ArticleStatusVO articleStatusVO = new ArticleStatusVO();
        articleStatusVO.setStatus(ArticleEnum.STATUS_YI_XIA_JIA.getValue());

        if (result) return R.success().msg("操作成功").data(articleStatusVO);
        return R.failure().msg("操作失败");*/
    }

    @SitePermission({GET_VERIFY_REASON_BY_ID})
    @ApiOperation(value = "根据id获取文章驳回原因", notes = "根据id获取文章驳回原因")
    @GetMapping("/get-verify-reason-by-id")
    public R<ArticleVerifyReasonVO> getVerifyReasonById(@ApiParam(value = "id", required = true, example = "12312313123") @RequestParam(required = false) Long id,
                                                        @ApiParam(value = "站点id(如果查询站点下的文章，则栏目id传0)", required = true, example = "123456789") @RequestParam(required = false) Long siteId,
                                                        @ApiParam(value = "当前栏目id", required = true, example = "12312313123") @RequestParam(required = false) Long columnId) {

        // 校验id
        if (id == null || !ValidateUtil.Number(id) || id <= 0) return R.failure().msg("id格式不正确");

        // 返回的VO
        ArticleVerifyReasonVO articleVerifyReasonVO = new ArticleVerifyReasonVO();

        // 根据id查找对应的文章对象
        ArticlePO articlePO = articleService.getById(id);
        if (null == articlePO) return R.resultCodeMsg(ResultCodeMsgEnum.DATA_NOT_EXIST);

        // 根据当前文章和文章的栏目以及当前栏目id 去 引用文章表 中查是否存在
        QueryWrapper<ColumnReferenceArticlePO> referenceArticlePOQueryWrapper = new QueryWrapper<>();
        referenceArticlePOQueryWrapper.eq("REFERENCE_ARTICLE_ID", articlePO.getId());
        referenceArticlePOQueryWrapper.eq("REFERENCE_COLUMN_ID", articlePO.getColumnId());
        referenceArticlePOQueryWrapper.eq("CURRENT_COLUMN_ID", columnId);
        ColumnReferenceArticlePO columnReferenceArticlePO = columnReferenceArticleService.getOne(referenceArticlePOQueryWrapper);
        // 不为空说明就是引用文章 去引用文章中查看理由
        if (null != columnReferenceArticlePO) {
            articleVerifyReasonVO.setVerifyReason(columnReferenceArticlePO.getVerifyReason());
        } else {
            // 为空就说明不是引用文章 去文章表查看理由
            articleVerifyReasonVO.setVerifyReason(articlePO.getVerifyReason());
        }
        /*// 封装到VO进行返回articleVerifyReasonVO
        articleVerifyReasonVO.setVerifyReason(articlePO.getVerifyReason());*/
        return R.success().data(articleVerifyReasonVO);
    }

    @SitePermission({MOVE_BY_ID})
    @ApiOperation(value = "根据id移动文章", notes = "根据id移动文章")
    @PutMapping("/move-by-id")
    public R moveById(@ApiParam(value = "id", required = true, example = "12312313123") @RequestParam(required = false) Long id,
                      @ApiParam(value = "栏目id", required = true, example = "1440511661143220226") @RequestParam(required = false) Long columnId,
                      @ApiParam(value = "站点id", required = true, example = "1435204946847760385") @RequestParam(required = false) Long siteId,
                      @RequestAttribute("userId") Long userId) {

        // 校验id
        if (id == null || !ValidateUtil.Number(id) || id <= 0) return R.failure().msg("id格式不正确");
        if (siteId == null || !ValidateUtil.Number(siteId) || siteId < 0)
            return R.failureRequestParam().msg("站点id为空或格式不正确");
        if (null == columnId || !ValidateUtil.Number(columnId) || columnId <= 0)
            return R.failureRequestParam().msg("栏目id为空或格式不正确");

        // 在草稿、待修改、已下架中的文章才可以移动 移动成功后状态默认设置为草稿
        ArrayList<String> statusList = new ArrayList<>();
        statusList.add(ArticleEnum.STATUS_CAO_GAO.getValue());
        statusList.add(ArticleEnum.STATUS_DAI_XIU_GAI.getValue());
        statusList.add(ArticleEnum.STATUS_YI_XIA_JIA.getValue());

        ArticlePO articlePOById = articleService.getById(id);
        String articleStatus = articlePOById.getArticleStatus();
        if (!statusList.contains(articleStatus)) return R.failure().msg("选中的文章不属于可移动的状态范围");

        // 开始移动
        ArticlePO articlePO = new ArticlePO();
        articlePO.setId(id);
        articlePO.setArticleStatus(ArticleEnum.STATUS_CAO_GAO.getValue());
        articlePO.setColumnId(columnId);
        articlePO.setSiteId(siteId);

        boolean result = articleService.updateById(articlePO);
        if (result) return R.success().msg("操作成功");
        return R.failure().msg("操作失败");
    }

    @SitePermission({MOVE_BY_IDS})
    @ApiOperation(value = "根据id批量移动文章", notes = "根据id批量移动文章")
    @PutMapping("/move-by-ids")
    public R moveByIds(@ApiParam(value = "文章id之间用英文逗号分隔", required = true, example = "12312313123,45678912312") @RequestParam(required = false) String ids,
                       @ApiParam(value = "栏目id", required = true, example = "1440511661143220226") @RequestParam(required = false) Long columnId,
                       @ApiParam(value = "站点id", required = true, example = "1435204946847760385") @RequestParam(required = false) Long siteId,
                       @RequestAttribute("userId") Long userId) {

        // 校验ids
        if (null == ids || StringUtils.isEmpty(ids)) return R.failureRequestParam().msg("请选择你要复制的文章id");
        if (siteId == null || !ValidateUtil.Number(siteId) || siteId < 0)
            return R.failureRequestParam().msg("站点id为空或格式不正确");
        if (null == columnId || !ValidateUtil.Number(columnId) || columnId <= 0)
            return R.failureRequestParam().msg("栏目id为空或格式不正确");
        // 先把字符串ids分割成数组idSplit
        String[] idSplit = ids.split(",");
        // 因为id是Long类型的 所以创建一个数组存放
        ArrayList<Long> idList = new ArrayList<>();
        // 对idSplit进行遍历 idSplit转换成Long类型的 添加到idList中
        for (String idString : idSplit) {
            Long id = Long.valueOf(idString);
            idList.add(id);
        }

        ArrayList<String> statusList = new ArrayList<>();
        statusList.add(ArticleEnum.STATUS_CAO_GAO.getValue());
        statusList.add(ArticleEnum.STATUS_DAI_XIU_GAI.getValue());
        statusList.add(ArticleEnum.STATUS_YI_XIA_JIA.getValue());

        // 查询id在范围内的集合对象
        QueryWrapper<ArticlePO> articlePOQueryWrapper = new QueryWrapper<>();
        articlePOQueryWrapper.in("ID", idList);
        List<ArticlePO> articlePOList = articleService.list(articlePOQueryWrapper);

        // 定义更新的集合
        ArrayList<ArticlePO> updateArticlePOList = new ArrayList<>();
        if (!ValidateUtil.isNullOrEmpty(articlePOList)) {
            for (ArticlePO articlePO : articlePOList) {
                String articleStatus = articlePO.getArticleStatus();
                if (!statusList.contains(articleStatus)) return R.failure().msg("选中的文章不属于可移动的状态范围");

                // 开始移动
                ArticlePO articleMovePO = new ArticlePO();
                articleMovePO.setId(articlePO.getId());
                articleMovePO.setArticleStatus(ArticleEnum.STATUS_CAO_GAO.getValue());
                articleMovePO.setColumnId(columnId);
                articleMovePO.setSiteId(siteId);
                updateArticlePOList.add(articleMovePO);


            }
        }
        boolean result = articleService.updateBatchById(updateArticlePOList);
        if (result) return R.success().msg("操作成功");
        return R.failure().msg("操作失败");
    }

    @SitePermission({GET_ARTICLE_STATUS_COUNT})
    @ApiOperation(value = "获取各文章状态的总数", notes = "获取各文章状态的总数")
    @GetMapping("/get-article-status-count")
    public R<ArticleStatusCountVO> getArticleStatusCount(@ApiParam(value = "站点id", required = true, example = "1444845498218246145") @RequestParam(required = false) Long siteId,
                                                         @ApiParam(value = "栏目id(如果只查询某栏目下的文章则传栏目id，如果查询整个站点下的文章则传0)", required = true, example = "1444845498218246145") @RequestParam(required = false) Long columnId) {
        if (siteId == null || !ValidateUtil.Number(siteId)) return R.failureRequestParam().msg("站点id不能为空");
        if (columnId == null || !ValidateUtil.Number(columnId)) return R.failureRequestParam().msg("栏目id不能为空");

        // 返回的数据
        ArticleStatusCountVO articleStatusCountVO = new ArticleStatusCountVO();

        // 栏目id不为0,查询栏目下的文章总数
        if (!columnId.equals(0L)) {
            // 查询未被回收的各个状态的文章总数
            QueryWrapper<ArticlePO> articlePOQueryWrapper = new QueryWrapper<>();
            articlePOQueryWrapper.eq("COLUMN_ID", columnId);
            articlePOQueryWrapper.eq("IS_RECOVERY", 0);
            articlePOQueryWrapper.select("COUNT(1) AS SITE_ID", "ARTICLE_STATUS");
            articlePOQueryWrapper.groupBy("ARTICLE_STATUS");
            List<ArticlePO> list = articleService.list(articlePOQueryWrapper);

            // 查询结果不为空时
            if (!ValidateUtil.isNullOrEmpty(list)) {
                int allCount = 0;
                for (ArticlePO articlePO : list) {
                    int count = Integer.parseInt(String.valueOf(articlePO.getSiteId()));
                    // 每一种状态的文章的总数
                    switch (articlePO.getArticleStatus()) {
                        case "CAO_GAO":
                            articleStatusCountVO.setCaoGaoCount(count);
                            allCount += count;
                            break;
                        case "DAI_SHEN_HE":
                            articleStatusCountVO.setDaiShenHeCount(count);
                            allCount += count;
                            break;
                        case "DAI_XIU_GAI":
                            articleStatusCountVO.setDaiXiuGaiCount(count);
                            allCount += count;
                            break;
                        case "YI_FA_BU":
                            articleStatusCountVO.setYiFaBuCount(count);
                            allCount += count;
                            break;
                        case "YI_XIA_JIA":
                            articleStatusCountVO.setYiXiaJiaCount(count);
                            allCount += count;
                            break;
                        case "YI_GUO_QI":
                            articleStatusCountVO.setYiGuoQiCount(count);
                            allCount += count;
                            break;
                    }
                }
                articleStatusCountVO.setAllCount(allCount);
            }

            // 查询已被回收的文章总数
            QueryWrapper<ArticlePO> articleQueryWrapper = new QueryWrapper<>();
            articleQueryWrapper.eq("COLUMN_ID", columnId);
            articleQueryWrapper.eq("IS_RECOVERY", 1);
            articleQueryWrapper.select("COUNT(1) AS SITE_ID");
            ArticlePO articlePORecovery = articleService.getOne(articleQueryWrapper);
            // 查询结果不为空才进入
            if (!ValidateUtil.isNullOrEmpty(articlePORecovery)) {
                articleStatusCountVO.setHuiSHouCount(Integer.parseInt(String.valueOf(articlePORecovery.getSiteId())));
            }
            // 栏目id为0，站点id不为0，查站点下的文章
        } else if (!siteId.equals(0L)) {
            // 栏目id为0，站点id不为0
            // 站点下未被回收的各个状态的文章总数
            QueryWrapper<ArticlePO> articlePOQueryWrapper = new QueryWrapper<>();
            // 站点下所有未被回收的栏目id
            List<Long> columnIdBySiteId = siteColumnService.getNotRecoveryColumnIdBySiteId(siteId);

            // 如果是空返回一个空VO
            if (ValidateUtil.isNullOrEmpty(columnIdBySiteId)) {
                return R.success().data(articleStatusCountVO);
            }

            // 到文章表中去查询，查出每个栏目下的文章状态
            articlePOQueryWrapper.in("COLUMN_ID", columnIdBySiteId);
            articlePOQueryWrapper.eq("IS_RECOVERY", 0);
            articlePOQueryWrapper.select("COUNT(1) AS SITE_ID", "ARTICLE_STATUS");
            articlePOQueryWrapper.groupBy("ARTICLE_STATUS");
            List<ArticlePO> list = articleService.list(articlePOQueryWrapper);

            if (!ValidateUtil.isNullOrEmpty(list)) {
                int allCount = 0;
                for (ArticlePO articlePO : list) {
                    int count = Integer.parseInt(String.valueOf(articlePO.getSiteId()));
                    // 每一种状态的文章的总数
                    switch (articlePO.getArticleStatus()) {
                        case "CAO_GAO":
                            articleStatusCountVO.setCaoGaoCount(count);
                            allCount += count;
                            break;
                        case "DAI_SHEN_HE":
                            articleStatusCountVO.setDaiShenHeCount(count);
                            allCount += count;
                            break;
                        case "DAI_XIU_GAI":
                            articleStatusCountVO.setDaiXiuGaiCount(count);
                            allCount += count;
                            break;
                        case "YI_FA_BU":
                            articleStatusCountVO.setYiFaBuCount(count);
                            allCount += count;
                            break;
                        case "YI_XIA_JIA":
                            articleStatusCountVO.setYiXiaJiaCount(count);
                            allCount += count;
                            break;
                        case "YI_GUO_QI":
                            articleStatusCountVO.setYiGuoQiCount(count);
                            allCount += count;
                            break;
                    }
                }
                articleStatusCountVO.setAllCount(allCount);
            }

            // 查询站点下已被回收文章总数
            // 站点下被回收的栏目
            QueryWrapper<ArticlePO> articleQueryWrapper = new QueryWrapper<>();
            List<Long> recoveryColumnIdBySiteId = siteColumnService.getRecoveryColumnIdBySiteId(siteId);
            if (ValidateUtil.isNullOrEmpty(recoveryColumnIdBySiteId)) {
                // 如果被回收的栏目是空
                articleQueryWrapper.eq("IS_RECOVERY", 1);
            } else {
                // 如果被回收的栏目不是空
                // 被回收的栏目下的文章，以及被回收的文章
                articleQueryWrapper.in("COLUMN_ID", recoveryColumnIdBySiteId).or().eq("IS_RECOVERY", 1);
            }
            articleQueryWrapper.eq("SITE_ID", siteId);
            articleQueryWrapper.select("COUNT(1) AS SITE_ID");
            ArticlePO recoveryCountPO = articleService.getOne(articleQueryWrapper);
            // 查询结果不为空才进入
            if (!ValidateUtil.isNullOrEmpty(recoveryCountPO)) {
                articleStatusCountVO.setHuiSHouCount(Integer.parseInt(String.valueOf(recoveryCountPO.getSiteId())));
            }

        }
        return R.success().data(articleStatusCountVO);

    }


    @SitePermission({GET_PC_TEMPLATE_RENDER_CONTENT})
    @ApiOperation(value = "预览PC端文章页面渲染内容", notes = "预览PC端文章页面渲染内容")
    @GetMapping("/get-pc-template-render-content")
    public R<String> getPCTemplateRenderContent(@ApiParam(value = "站点id", required = true, example = "123456789") @RequestParam(required = false) Long siteId,
                                                @ApiParam(value = "栏目id", required = true, example = "123456789") @RequestParam(required = false) Long columnId,
                                                @ApiParam(value = "文章id", required = true, example = "123456789") @RequestParam(required = false) Long articleId) {

        // 参数校验
        if (siteId == null || !ValidateUtil.Number(siteId) || siteId <= 0)
            return R.failureRequestParam().msg("站点id不能为空");

        if (columnId == null || !ValidateUtil.Number(columnId) || columnId <= 0)
            return R.failureRequestParam().msg("栏目id不能为空");

        if (articleId == null || !ValidateUtil.Number(articleId) || articleId <= 0)
            return R.failureRequestParam().msg("文章id不能为空");

        // 查询站点信息
        SitePO sitePO = siteService.getById(siteId);
        if (ValidateUtil.isNullOrEmpty(sitePO)) return R.resultCodeMsg(ResultCodeMsgEnum.DATA_NOT_EXIST);

        // 查询栏目信息
        ColumnPO columnPO = columnService.getById(columnId);
        if (ValidateUtil.isNullOrEmpty(columnPO)) return R.resultCodeMsg(ResultCodeMsgEnum.DATA_NOT_EXIST);

        // 查询文章信息
        ArticlePO articlePO = articleService.getById(articleId);
        if (ValidateUtil.isNullOrEmpty(articlePO)) return R.resultCodeMsg(ResultCodeMsgEnum.DATA_NOT_EXIST);

        QueryWrapper<StaticLogPO> staticLogPOQueryWrapper = new QueryWrapper<>();
        staticLogPOQueryWrapper.eq("SITE_ID", siteId);
        staticLogPOQueryWrapper.eq("COLUMN_ID", columnId);
        staticLogPOQueryWrapper.eq("ARTICLE_ID", articleId);
        staticLogPOQueryWrapper.eq("STATUS", StaticHtmlStatusEnum.JIN_XING_ZHONG.getValue());
        staticLogPOQueryWrapper.eq("STATIC_TYPE", StaticHtmlTypeEnum.ARTICLE.getValue());
        StaticLogPO staticLogPO = staticLogService.getOne(staticLogPOQueryWrapper, false);
        if (null != staticLogPO && null != staticLogPO.getId()) {
            return R.failure().msg("静态化任务正在进行,请稍后再试!");
        }

        // 拼接路径
        String storageStaticPath = siteService.getStorageStaticPath(sitePO.getId());
        String pcStorageStaticPath = storageStaticPath + File.separator + "pc";

        // 拷贝到预览目录下
        File file = FileUtil.file(previewPath + columnPO.getEncodedXpath() + File.separator + "article" + File.separator + articleId + ".html");
        // 1、静态化页面
        File sourceFile = FileUtil.file(pcStorageStaticPath + columnPO.getEncodedXpath() + File.separator + "article" + File.separator + articleId + ".html");
        FileUtil.copyContent(sourceFile, file, true);
        // 2、静态文件
        // 目标路径对象
        File targetFile = FileUtil.file(previewPath + File.separator + "static");
        File sourceStaticFile = FileUtil.file(pcStorageStaticPath + File.separator + "static");
        FileUtil.copyContent(sourceStaticFile, targetFile, true);

        String previewColumn = previewUrl + columnPO.getEncodedXpath() + "/article/" + articleId + ".html";

        return R.success().data(previewColumn);
    }

    @SitePermission({GET_H5_TEMPLATE_RENDER_CONTENT})
    @ApiOperation(value = "预览H5端文章页面渲染内容", notes = "预览H5端文章页面渲染内容")
    @GetMapping("/get-h5-template-render-content")
    public R<TemplateRenderVO> getH5TemplateRenderContent(@ApiParam(value = "站点id", required = true, example = "123456789") @RequestParam(required = false) Long siteId,
                                                          @ApiParam(value = "栏目id", required = true, example = "123456789") @RequestParam(required = false) Long columnId,
                                                          @ApiParam(value = "文章id", required = true, example = "123456789") @RequestParam(required = false) Long articleId) {


        // 参数校验
        if (siteId == null || !ValidateUtil.Number(siteId) || siteId <= 0)
            return R.failureRequestParam().msg("站点id不能为空");

        if (columnId == null || !ValidateUtil.Number(columnId) || columnId <= 0)
            return R.failureRequestParam().msg("栏目id不能为空");

        if (articleId == null || !ValidateUtil.Number(articleId) || articleId <= 0)
            return R.failureRequestParam().msg("文章id不能为空");

        // 查询站点信息
        SitePO sitePO = siteService.getById(siteId);
        if (ValidateUtil.isNullOrEmpty(sitePO)) return R.resultCodeMsg(ResultCodeMsgEnum.DATA_NOT_EXIST);

        // 查询栏目信息
        ColumnPO columnPO = columnService.getById(columnId);
        if (ValidateUtil.isNullOrEmpty(columnPO)) return R.resultCodeMsg(ResultCodeMsgEnum.DATA_NOT_EXIST);

        // 查询文章信息
        ArticlePO articlePO = articleService.getById(articleId);
        if (ValidateUtil.isNullOrEmpty(articlePO)) return R.resultCodeMsg(ResultCodeMsgEnum.DATA_NOT_EXIST);

        QueryWrapper<StaticLogPO> staticLogPOQueryWrapper = new QueryWrapper<>();
        staticLogPOQueryWrapper.eq("SITE_ID", siteId);
        staticLogPOQueryWrapper.eq("COLUMN_ID", columnId);
        staticLogPOQueryWrapper.eq("ARTICLE_ID", articleId);
        staticLogPOQueryWrapper.eq("STATUS", StaticHtmlStatusEnum.JIN_XING_ZHONG.getValue());
        staticLogPOQueryWrapper.eq("STATIC_TYPE", StaticHtmlTypeEnum.ARTICLE.getValue());
        StaticLogPO staticLogPO = staticLogService.getOne(staticLogPOQueryWrapper, false);
        if (null != staticLogPO && null != staticLogPO.getId()) {
            return R.failure().msg("静态化任务正在进行,请稍后再试!");
        }

        // 拼接路径
        String storageStaticPath = siteService.getStorageStaticPath(sitePO.getId());
        String pcStorageStaticPath = storageStaticPath + File.separator + "pc" + File.separator + "h5";

        // 拷贝到预览目录下
        File file = FileUtil.file(previewPath + File.separator + "h5" + columnPO.getEncodedXpath() + File.separator + "article" + File.separator + articleId + ".html");
        // 1、静态化页面
        File sourceFile = FileUtil.file(pcStorageStaticPath + columnPO.getEncodedXpath() + File.separator + "article" + File.separator + articleId + ".html");
        FileUtil.copyContent(sourceFile, file, true);
        // 2、静态文件
        // 目标路径对象
        File targetFile = FileUtil.file(previewPath + File.separator + "h5"  + File.separator + "static");
        File sourceStaticFile = FileUtil.file(pcStorageStaticPath + File.separator + "static");
        FileUtil.copyContent(sourceStaticFile, targetFile, true);

//        String s = columnPO.getEncodedXpath().replaceAll("\\\\", "/");

        String previewColumn = previewUrl + columnPO.getEncodedXpath() + "/article/" + articleId + ".html";

        return R.success().data(previewColumn);
    }
}
